Friday, 23 September 2022

Fight Internet Censorship - Run a Snowflake Proxy

 Why run a snowflake proxy?

News reports indicate that current events caused a sharp increase in blocked or limited internet accessibility in several countries. One option to circumvent these measures is to use a TOR browser. Also available on mobile phones - e.g. Onion Browser for iOS.

In the cable tray under my desk, there lives a Raspberry Pi

As one method to aid circumventing DNS, IP and routing measures, you can run a snowflake proxy. Your PC or server temporarily registers with a public broker as a snowflake proxy. A user's TOR browser will ask the broker for the address of a snowflake proxy, which will give access to the TOR network. Snowflake is one of several bridging techniques that can be chosen in the browser if it can't connect to the TOR network directly.

Snowflake Schematic (originally from here)

Can I get in trouble for running a snowflake proxy?

If you live in a healthy democracy, it is most unlikely to get into trouble for running a snowflake proxy. Other than running a TOR Exit Node (very bad idea!), your IP address won't show up in any web server logs.

Can anyone do bad things over my connection?

Yes. But you will never know, as all communication is encrypted. Like any technology, TOR can be used for good and bad. - I decided that at this moment the benefits outweigh the risks. I hope that will change some time soon.

If you don't run a dedicated server, consider running snowflake as a plugin for Firefox or chrome, so you can help while surfing the web.

Will it eat up my Internet bandwidth?

That depends. It does not even remotely for me, but I have the luxury of a super stable 100/40 MBit/s DSL connection.

Set up Snowflake on a Raspberry Pi

There are several tutorials on the web, but none worked flawlessly 1st try. So here is my take. I assume you have a basic knowledge of Linux/Unix.

Fetch the current version of the GO programming language for the Raspi:

me@myhost:$ wget https://go.dev/dl/go1.19.1.linux-armv6l.tar.gz

--2022-09-22 14:32:59--  https://go.dev/dl/go1.19.1.linux-armv6l.tar.gz
.... much Output deleted .....
go1.19.1.linux-armv6l.tar 100%[===================================>] 111,29M  1,38MB/s    in 33s
2022-09-22 14:33:32 (3,42 MB/s) - »go1.19.1.linux-armv6l.tar.gz« saved [116690970/116690970]

Unpack that to /usr/local (or wherever you like it best):

me@myhost:$ sudo tar -C /usr/local -xzf go1.19.1.linux-armv6l.tar.gz

You can get rid og the archive to free up the space:

me@myhost:$ rm go1.19.1.linux-armv6l.tar.gz

Add the location of the go binary to your path to make things easy:

me@myhost:$ vi ~/.profile

At the end of the file simply add these two lines:

PATH=$PATH:/usr/local/go/bin
GOPATH=$HOME/go

Save that (ESC : w q)

You can now either log off and on again, or type

me@myhost:$ source ~/.profile

to update the environment variables.

If you haven't installed git already, do so by typing:

me@myhost:$ sudo apt install git

If you have a preferred directory where you build your stuff, cd to there. Otherwise just type:

me@myhost:$ git clone https://git.torproject.org/pluggable-transports/snowflake.git

Then change to the proxy subdirectory:

me@myhost:$ cd snowflake
me@myhost:$ cd proxy

And build the snowflake proyx:

me@myhost:$ go build

Once that has completed, you can run it right from where you are:

me@myhost:~/snowflake/proxy $ ./proxy -verbose

2022/09/24 14:01:55 starting
2022/09/24 14:01:56 WebRTC: Created offer
2022/09/24 14:01:56 WebRTC: Set local description
2022/09/24 14:01:56 Offer:... OUTPUT REMOVED
2022/09/24 14:02:25 NAT Type measurement: unknown -> restricted = restricted
2022/09/24 14:02:25 NAT type: restricted
2022/09/24 14:02:35 sdp offer successfully received.
2022/09/24 14:04:48 OnDataChannel
2022/09/24 14:04:48 Connection successful.
2022/09/24 14:04:48 OnOpen channel
2022/09/24 14:10:56 connected to relay: wss://snowflake.torproject.net/
2022/09/24 14:10:58 OnClose channel
2022/09/24 14:10:58 Traffic throughput (up|down): 8 KB|11 KB -- (43 OnMessages, 16 Sends, over 15 seconds)
2022/09/24 14:10:58 copy loop ended
2022/09/24 14:10:58 datachannelHandler ends

It might take a while for someone to actually connect. Don't worry if you see time-outs.

CTRL-C ends the process. On a Raspberry Pi, you'll probably want to run the proxy even while logged off. My way of doing that is not what you'd want for a permanent installation. As I do a lot of experimental stuff on the Raspi, I like to manually start what I want to run:

me@myhost:$ nohup ./proxy > ~/snowflake.log 2>&1 &

That has the downside that you manually have to kill the process when you want to stop it. 

me@myhost:$ kill -9 $(pidof proxy)

Some extra load on the Raspi

The proxy takes a fair bit of CPU power from the Raspberry. But it never even comes close to using the full capacity and the sub processes balance nicely over the four cores of my somewhat aged pi.

Moderate extra load on the Raspberry Pi

Sniffing snowflake traffic on your network

You can actually find out where the users using your proxy are located. As the clients connect (well, it is UDP, so strictly speaking "connect" is not quite right) to your proxy, you can use tcpdump for a quick analysis:

me@myhost:$ sudo tcpdump -i eth0 -s 1500 port not 22 and port not 53

On the output, look out for UDP traffic. There will be some lines looking like this:
18:09:46.914455 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.914894 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.915551 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.915987 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.916724 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.917321 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.918309 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 1265
18:09:46.919010 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 269
18:09:46.919814 IP myhost.mydomain.de.60101 > 188.208.20Y.XXX.39043: UDP, length 1265

To protect the user, I edited out the full IP.
The IP (or possibly hostname, if it can be resolved) can be fed to the excellent Domain Dossier web site from Centralops.net for analysis.

The Network whois record will show who owns that network and where the company is located. In this case it is (no wonder at this moment) in Teheran, Iran.
That result was to be expected
From a brief observation, I see almost exclusively IPs from providers in Iran, Iraq and Russia.

The slowflake log

When not in verbose mode, the proxy logs to stdout (or in my case to snowflake.log) hourly and reports some statistics:
me@myhost:~ $ tail -f snowflake.log
2022/09/18 04:12:49 In the last 1h0m0s, there were 7 connections. Traffic Relayed ↑ 1 GB, ↓ 87 MB.
2022/09/18 05:12:49 In the last 1h0m0s, there were 8 connections. Traffic Relayed ↑ 3 MB, ↓ 487 KB.
2022/09/18 06:12:49 In the last 1h0m0s, there were 20 connections. Traffic Relayed ↑ 327 MB, ↓ 34 MB.
2022/09/18 07:12:49 In the last 1h0m0s, there were 17 connections. Traffic Relayed ↑ 14 MB, ↓ 4 MB.
2022/09/18 08:12:49 In the last 1h0m0s, there were 34 connections. Traffic Relayed ↑ 46 MB, ↓ 18 MB.
2022/09/18 09:12:49 In the last 1h0m0s, there were 15 connections. Traffic Relayed ↑ 23 MB, ↓ 12 MB.
2022/09/18 10:12:49 In the last 1h0m0s, there were 40 connections. Traffic Relayed ↑ 286 MB, ↓ 70 MB.
2022/09/18 11:12:49 In the last 1h0m0s, there were 19 connections. Traffic Relayed ↑ 46 MB, ↓ 15 MB.
2022/09/18 12:12:49 In the last 1h0m0s, there were 27 connections. Traffic Relayed ↑ 134 MB, ↓ 35 MB.
2022/09/18 13:12:49 In the last 1h0m0s, there were 13 connections. Traffic Relayed ↑ 32 MB, ↓ 3 MB.

The traffic volume varies widely from a few MBytes s to a GByte per hour.


Friday, 24 June 2022

Fixing broken VNC dependencies on Raspberry PI

 Out of the blue, when updating my Raspberry threw this error:

users@host:~ $ sudo apt-get upgrade

Paketlisten werden gelesen... Fertig

Abhängigkeitsbaum wird aufgebaut.

Statusinformationen werden eingelesen.... Fertig

Paketaktualisierung (Upgrade) wird berechnet... Fertig

Einige Pakete konnten nicht installiert werden. Das kann bedeuten, dass

Sie eine unmögliche Situation angefordert haben oder, wenn Sie die

Unstable-Distribution verwenden, dass einige erforderliche Pakete noch

nicht erstellt wurden oder Incoming noch nicht verlassen haben.

Die folgenden Informationen helfen Ihnen vielleicht, die Situation zu lösen:


Die folgenden Pakete haben unerfüllte Abhängigkeiten:

 vlc-bin : Hängt ab von: libvlc-bin (= 3.0.12-0+deb10u1+rpt3) aber 3.0.17.4-0+deb10u1 soll installiert werden

 vlc-plugin-base : Hängt ab von: vlc-data (= 3.0.12-0+deb10u1+rpt3) aber 3.0.17.4-0+deb10u1 soll installiert werden

 vlc-plugin-skins2 : Hängt ab von: vlc-plugin-qt (= 3.0.17.4-0+deb10u1) aber 3.0.12-0+deb10u1+rpt3 soll installiert werden

E: Beschädigte Pakete

Damaged packets? Broken depencencies? Her is what helped:

user@host:~ $ sudo apt-get install --reinstall vlc-bin

And after a little while sudo apt-get upgrade ran without any issues

Tuesday, 11 January 2022

Arduino HTTP client connection through corporate proxy server

Connecting an Arduino to the web via a http proxy

http Proxies

There are a variety of reasons why you'd want to have a http-Proxy in a corporate environment. Security, content filtering, authentication and authorization, as well as logging and traffic optimization.
And it makes a lot of sense to not point the default gateway of a corporate network towards the internet, as this raises the bar for malicious software (and users) to bypass network security. But that means that software that needs to access the internet has to do so through the proxy server.
This example has been tried through a SQUID proxy with more or less default configuration.

Arduino http client

The Arduino ethernet library provides sufficient functionality to get basic tasks done. In this case get the weather feed from BBC for a specific location. But with a little twist: It only speaks to the proxy server.
Example Setup

Modified "Web Client" example

This is just a slightly modified version of the "Examples->Ethernet->WebClient" that comes with the Arduino IDE and an installed Ethernet library. Works as show with an Arduino MKR Zero, but should work with an UNO just as well.


 /*  
  Web proxy client  
  This sketch reads an RSS feed from a website  
  using an Arduino Wiznet Ethernet shield.  
  Circuit:  
  * Ethernet shield attached to pins 10, 11, 12, 13  
  created 18 Dec 2009  
  by David A. Mellis  
  modified 9 Apr 2012  
  by Tom Igoe, based on work by Adrian McEwen  
  modified 11 Jan 2022  
  by Andy Reischle for http proxy support  
  */  
 #include <SPI.h>  
 #include <Ethernet.h>  
 // Enter a MAC address for your controller below.  
 // Newer Ethernet shields have a MAC address printed on a sticker on the shield  
 // Don't forget to change that when you have more than one of these on one network segment  
 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
 // if you don't want to use DNS (and reduce your sketch size)  
 // use the numeric IP instead of the name for the server:  
 //IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)  
 char server[] = "weather-broker-cdn.api.bbci.co.uk";  // name address for target server (using DNS)  
 char proxy[] = "proxy.internal.mycorporation.something"; // name of the internal proxy server (using DNS)  
 // Set the static IP address to use if the DHCP fails to assign  
 // That will be rather pointless in a corporate environment  
 IPAddress ip(192, 168, 0, 177);  
 IPAddress myDns(192, 168, 0, 1);  
 // Initialize the Ethernet client library  
 // with the IP address and port of the server  
 // that you want to connect to (port 80 is default for HTTP):  
 EthernetClient client;  
 // Variables to measure the speed  
 unsigned long beginMicros, endMicros;  
 unsigned long byteCount = 0;  
 bool printWebData = true; // set to false for better speed measurement  
 void setup() {  
  // You can use Ethernet.init(pin) to configure the CS pin  
  //Ethernet.init(10); // Most Arduino shields  
  Ethernet.init(5);  // MKR ETH shield  
  //Ethernet.init(0);  // Teensy 2.0  
  //Ethernet.init(20); // Teensy++ 2.0  
  //Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet  
  //Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet  
  // Open serial communications and wait for port to open:  
  Serial.begin(9600);  
  while (!Serial) {  
   ; // wait for serial port to connect. Needed for native USB port only  
  }  
  // start the Ethernet connection:  
  Serial.println("Initialize Ethernet with DHCP:");  
  if (Ethernet.begin(mac) == 0) {  
   Serial.println("Failed to configure Ethernet using DHCP");  
   // Check for Ethernet hardware present  
   if (Ethernet.hardwareStatus() == EthernetNoHardware) {  
    Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");  
    while (true) {  
     delay(1); // do nothing, no point running without Ethernet hardware  
    }  
   }  
   if (Ethernet.linkStatus() == LinkOFF) {  
    Serial.println("Ethernet cable is not connected.");  
   }  
   // try to configure using IP address instead of DHCP:  
   Ethernet.begin(mac, ip, myDns);  
  } else {  
   Serial.print(" DHCP assigned IP ");  
   Serial.println(Ethernet.localIP());  
  }  
  // give the Ethernet shield a second to initialize:  
  delay(1000);  
  Serial.print("connecting to ");  
  Serial.print(proxy);  
  Serial.println("...");  
  // if you get a connection, report back via serial:  
  // target the request to the proxy  
  if (client.connect(proxy, 8080)) {  
   Serial.print("connected to ");  
   Serial.println(client.remoteIP());  
   // Make a HTTP request to the proxy:  
   client.println("GET http://weather-broker-cdn.api.bbci.co.uk/en/observation/rss/2907669 HTTP/1.1");  
   client.println("Host: weather-broker-cdn.api.bbci.co.uk");  
   client.println("Connection: close");  
   client.println();  
  } else {  
   // if you didn't get a connection to the server:  
   Serial.println("connection failed");  
  }  
  beginMicros = micros();  
 }  
 void loop() {  
  // if there are incoming bytes available  
  // from the server, read them and print them:  
  int len = client.available();  
  if (len > 0) {  
   byte buffer[80];  
   if (len > 80) len = 80;  
   client.read(buffer, len);  
   if (printWebData) {  
    Serial.write(buffer, len); // show in the serial monitor (slows some boards)  
   }  
   byteCount = byteCount + len;  
  }  
  // if the server's disconnected, stop the client:  
  if (!client.connected()) {  
   endMicros = micros();  
   Serial.println();  
   Serial.println("disconnecting.");  
   client.stop();  
   Serial.print("Received ");  
   Serial.print(byteCount);  
   Serial.print(" bytes in ");  
   float seconds = (float)(endMicros - beginMicros) / 1000000.0;  
   Serial.print(seconds, 4);  
   float rate = (float)byteCount / seconds / 1000.0;  
   Serial.print(", rate = ");  
   Serial.print(rate);  
   Serial.print(" kbytes/second");  
   Serial.println();  
   // do nothing forevermore:  
   while (true) {  
    delay(1);  
   }  
  }  
 }  
If all goes well, this is the output:

Initialize Ethernet with DHCP:
  DHCP assigned IP 1.2.3.4
connecting to proxy.internal.mycorporation.something...
connected to 4.3.2.1
HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/rss+xml
ETag: "8b0e69972930952dc99c4d239b1c489402f5940392a0bbe16ed534b0b242787f"
expiry_extended_seconds: 0
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
Cache-Control: no-transform, max-age=60
Date: Tue, 11 Jan 2022 18:37:23 GMT
Content-Length: 1660
X-Cache: MISS from proxy.internal.mycorporation.something
X-Cache-Lookup: MISS from proxy.internal.mycorporation.something:8080
Via: 1.0 proxy.internal.mycorporation.something:8080 (squid/2.6.STABLE21)
Proxy-Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:georss="http://www.georss.org/georss" version="2.0">
  <channel>
    <title>BBC Weather - Observations for  Heilbronn, DE</title>
    <link>https://www.bbc.co.uk/weather/2907669</link>
    <description>Latest observations for Heilbronn from BBC Weather, including weather, temperature and wind information</description>
    <language>en</language>
    <copyright>Copyright: (C) British Broadcasting Corporation, see http://www.bbc.co.uk/terms/additional_rss.shtml for more details</copyright>
    <pubDate>Tue, 11 Jan 2022 17:00:00 GMT</pubDate>
    <dc:date>2022-01-11T18:00:00Z</dc:date>
    <dc:language>en</dc:language>
    <dc:rights>Copyright: (C) British Broadcasting Corporation, see http://www.bbc.co.uk/terms/additional_rss.shtml for more details</dc:rights>
    <atom:link href="https://weather-service-thunder-broker.api.bbci.co.uk/en/observation/rss/2907669" type="application/rss+xml" rel="self" />
    <item>
      <title>Tuesday - 18:00 CET: Not available, 4°C (40°F)</title>
      <link>https://www.bbc.co.uk/weather/2907669</link>
      <description>Temperature: 4°C (40°F), Wind Direction: Easterly, Wind Speed: 4mph, Humidity: 66%, Pressure: 1033mb, Rising, Visibility: --</description>
      <pubDate>Tue, 11 Jan 2022 18:00:00 GMT</pubDate>
      <guid isPermaLink="false">https://www.bbc.co.uk/weather/2907669-2022-01-11T18:00:00.000+01:00</guid>
      <dc:date>2022-01-11T17:00:00Z</dc:date>
      <georss:point>49.1399 9.2205</georss:point>
    </item>
  </channel>
</rss>

disconnecting.
Received 2181 bytes in 0.4765, rate = 4.58 kbytes/second

No big deal extracting values from that output. I've done something similar here:
Fritzmeter Project , but with TinyXML you should be able to do that with more style.

The proxy log (acces.log) entry shows:
1.2.3.4 TCP_MISS/200 2181 GET http://weather-broker-cdn.api.bbci.co.uk/en/observation/rss/2907669 - DIRECT/184.86.251.134 application/rss+xml


What about HTTPS?

The Arduino Uno is to anemic for HTTPS, but the experiments on this page have been done with a MKR ZERO and the matching MKR ETH Shield. The MKR ZERO can do HTTPS easily.
But:
HTTPS through a http-proxy works differently from HTTP: The client requests a tunneled connection from the Proxy, using the "CONNECT" method (rather than "GET" in the HTTP example).
The otherwise brilliant SSLClient library does not provide an obvious way to support that:
I have not yet found a way to establish that first part of the connection request without encryption and switch to SSL/TLS after the tunnel is initiated.

Thursday, 20 May 2021

SRH 789 (clone) antenna mod for hackRF Portapack

SRH 789 antenna modification

The Portapack

The Portapack (in my case, the H1) ist a great addition to the hackrf one. After I had damaged two hackrfs, my current setup now uses the version with a modified RF-frontend by Clifford Heath. This now works safely alongside my ham radio gear.

My portapack setup
It covers all ham bands from 160m to 6cm (any anything inbetween). In practise, it starts becoming useable at 80m up to 23cm. Beyond that, I don't own suitable antennas and/or preamps / filters.

VHF contest

Although the latest version of the Mayhem firmware now supports SSB-TX, I would not stand much of a chance in a contest with the portapack as main rig. But my trusty old 1980s FT-290 that I still like to use for portable operations, does not offer any of the luxuries that we came to expect from modern transceivers. So I like seeing the section of the band I am working on, on the portapack.
Not so this time. The strongest stations that were 59plus on the FT-290 barely showed up on the spectrum view.
The HackRF is not the greatest receiver there is with it's total lack of band filtering or preselectors and I suspected the nearby FM Radio tower to interfere.
The same disappointment a little later, when I was out, hunting a radiosonde that practically should have been on top of me. Something with my setup was very wrong.

The Antenna

I often used a 2m/70cm dual band antenna on the portapack, but a while ago I got a cheap clone of the Diamond SRH789 antenna, which should have been more than good enough for the job and does not poke through my backpack.
Not the original SRH789

So back home in the shack, I checked the SRH 780 against the dual band antenna and it became quite obvious that the problem did not lie with the HackRF this time.
Having nothing to loose, I took the antenna apart and was surprised to find a totally pointless plastic piece between the center connector of the SMA side and the telescopic whip. The copper wire that had once bridged the plastic piece had torn off when I rotated the antenna.
The antenna is obviously not meant to be treated that way, but with the portapack sitting on the ground, I need the antenna to point up, of course.
There is absolutely no L/C matching RF-magic going on in the antenna base. So there is no point in keeping that plastic bit there.
No RF will pass this
Fortunately it has M4 threads on both ends, so an M4 screw will be a simple, more RF friendly replacement.

M4 fits just fine. The copper wire can be removed
If you want, you can yank out the glued in center conductor, so the aerial can spin more freely. 
With a sharp pull, the center pin of the SMA connector comes loose

When I put it all back together, I took the antenna through it's paces with the NanoVNA. Not surprisingly, I got mixed results. This is to be expected from an antenna that is nothing but a piece of iron rod sticking out the back of the transceiver.
Radials? Counterpoise? GroundPlane? Nope.
The resonant frequency varied wildly with the surrounding conditions. i.e. me touching the VNA's case or leaning over my workbench. With some tuning you'll get an acceptable SWR all through the 100MHZ zo 1.1 GHz range. The impedance is a different story: While somewhere around 50 Ohms for 2m and 70cm, where the antenna works as a quarter wave, the impedance on the higher bands is all over the place.

Final word

This is not a great antenna. You can't expect miracles. Possibly because it is a fake/counterfeit product.The original Diamond antenna may be a better choice. Please leave a comment if you have one.
As a mainly RX-antenna with superb portability it is acceptable, but no match for TX-capable wideband discone (that will be significantly bigger and more expensive).



Thursday, 25 February 2021

Iphone 12 hearing aid compatibility problem

iPhone 12 bluetooth hearing aid compatibility issue (and a "works-for-me" solution)

More on that issue, including audio samples shortly on my YouTube channel.

No problems with iPhone 8

I had an iPhone 8 for the last 3 or so years, and just by the end of last year, I upgraded my hearing aid to the latest&greatest Li-Ion powered bluetooth connected version I could get my hands on.

Specs & hearing aid - no problem.
Things become tricky with a mask.

Apart from better hearing, the additional bonus of having a top quality, hands-free, near invisible headset for the numerous audio and video conferences that came with the pandemic was just a blast.

Until I switched to an iPhone 12.

The hearing aid

It seems that there is only a small number of actual manufacturers and a lot of brand names hearing aids are sold under. Mine are sold as SoniTon UP5 R Li with a CE 0543 mark that indicates it has been certified as a medical device in Denmark.

The actual manufacturer seems so be Unitron Hearing Ltd. in Canada. Other names/brands the device is sold under are: Vista DX 350 R Li, AudioNova DX 30 R Li, DX Moxi Move R 3, scala DX 350 R Li, excellence 2 V2 R Li

It is not specifically "made for iPhone", but can be used universally, so while the use as headset/headphones is generic, control is via Bluetooth LE and a "hearing remote" app.

The "hearing remote" app allows control via the iPhone

iPhone 12 problems

At first I didn't notice anything wrong. Podcasts and music were fine to listen to. But callers and team-mates complained about choppy, scratchy audio. Same thing on my side: distorted audio.

I went investigating and found that to be a common problem for people using the iPhone 12 series (mini, pro and "regular" alike). Even for hearing aids specifically "Made for iPhone. The sterotypical recommendation to use the latest iOS version as found on Apple's support and discussion pages were useless for me. Apple claims to have it solved for "Made for iPhone" with iOS 14.2.1, which left me on my own.

The solution

It appears, that the problem lies with "Adaptive Bluetooth". I am not sure which flavour of "Adaptive Bluetooth" that is, since both "adaptive frequency hopping" and "adaptive codec selection" (Qualcomm aptX Adaptive) are "adaptive". If you know, please leave a note in the comments.

Disable Adaptive Bluetooth
Adaptive bluetooth can be disabled in the "remote hearing" app. The hearing aids have to be restarted after changing that setting.

With this setting changed, calls, voice recordings and video conferences are ok again. I am not quite sure whether or not I sense a very slightly reduced audio quality for music since then. If so, the codec chosen for compatibility might not be the best for music.


Sunday, 27 December 2020

Strange serial port issue with Arduino nano 33 sense ble

Serial port problems with Arduino nano 33 sense

Can't upload sketch / Can't connect via Putty or serial monitor

I gave myself a nano Christmas present: A brand new Arduino Nano 33 Sense BLE. Mainly because I wanted to try out machine learning with TinyML, but the book from O'Reilly is still in the mail.

Tiny, but with lots of sensors

So I started exploring Bluetooth LE, trying to master that skill first. It was a slightly bumpy ride because from time to time the Arduino IDE switched the serial port to COM5, while the Arduino clearly was on COM7 (these will very likely be different on your PC)

The nano 33 on COM7

I reset the arduino a couple of times, but I couldn't get it to communicate via COM7, although the port was clearly present in Windows.

Double click the reset button

More or less by chance I double-clicked the reset button. And - whatdoyouknow - I had the Nano on COM5. - How strange!

The nano 33 on COM5
Now I could upload sketches again. - Ok. But COM port assignments in Windows don't change without a good reason. Let's dig deeper.

USB device tree viewer

Uwe Sieber has published a great, free tool "USB tree viewer", that shows all the details of all attached USB devices. I can then copy both (the COM7 and COM5) configurations to Notepad++ and run the Compare-Plugin.

As expected, the double click on the reset button lets the nano 33 appear as a very different device:

While the Vendor ID is alwaysd 0x2341 (Arduino SA), the product ID changes from 0x805A to 0x005A. The device ID, revision number and sleep modes also change.

The device descriptor string 2 changes from "Nano 33 BLE" to "Arduino Nano 33 BLE" string descriptor 3 is the same, but padded with leading "0"s.

Looks like two different devices

No wonder Windows sees that as a new device. I have no idea what the point in all that is.

Please leave a comment if you have more info.


EDIT 20210107:
The behavior is actually documented in the documentation:

If the board does not enter the upload mode, please do a double press on the reset button before the upload process is initiated; the orange LED should slowly fade in and out to show that the board is waiting for the upload.

I still find the "nano 33 ble sense" rather unpleasant to work with because of that.

Friday, 25 December 2020

Macbook late 2008 SSD upgrade

Macbook SSD upgrade

With only 2GByte of RAM and an out-of-support El Capitan (OSX 10.11), the 12 year old MacBook is somewhere between "ready for recycling" and "too good to waste". Over time it had become unbearably sluggish. So with prior good results on Windows PCs from the same era, I decided to give it a go.

It is super easy and reasonably safe even for intrepid  beginners.

SSD selection

I tend to go for maior brands whenever affordable. Amazon had a 500GByte Samsung 860 EVO for cheap on Black Friday 2020, so that ist the SSD of choice. The person using the Mac as a mail and browse machine will never even come near the full capacity of that disk.

Preparations / backup

A full time machine backup on an external USB drive is all it takes to recover the installation to a new SSD.

Physical installation

These old devices are built to last and to be serviced: Just remove the bottom cover (unlock with lever). Remove the disk holder (black plastic bar) with a small Phillips screw driver and lift out the old disk by the pull-tab.

Carefully remove the SATA connector from the left side of the old hard disk.

Remove the four small bolts that held the disk in place and install them on the new SSD

Reconnect the SATA connector

Insert the SSD and fix it with the plastic bar.

Close the battery/harddisk cover.

SSD preparation

Attach the USB drive with the Time Machine backup to a USB port.

After a little wait, the MacBook will boot from the USB drive.

A menue comes up: There choose the hard disk utility and add a partition to the SSD (accept the first file system option).

Go back to the previous menu

Restore from Time Machine Backup

Choose your Time Machine Backup Disk and select the latest backup.

Wait for the restore to complete

Wait for the restore to finish and reboot

Tell the Mac where to boot from

It speeds up the boot process a lot when you set the new SSD as the boot device in the settings. Otherwise it takes a while to find bootable devices.

That relatively cheap upgrade saved the nearly unuseable machine from the junk yard. With only two 1GByte RAM modules installed, the next option is to go for more memory. With the last published firmware version, this machine supports up to 8GByte.