# notes * grab a raspberry pi 1 b+ from the rpi bin * download debian image for this old rpi * boot then adduser * `apt install sudo vim tmux git rsync usbutils bluetooth bluez bluez-tools rfkill` ## troubleshooting List of linux connected bluetooth interfaces ``` # hcitool dev Devices: hci0 00:1A:7D:DA:71:15 # sudo hcitool -i hci0 lescan LE Scan ... CF:CD:27:79:55:6B FR:R20:SN1735 C9:31:F4:9A:B1:86 (unknown) CF:CD:27:79:55:6B (unknown) CF:CD:27:79:55:6B FR:R20:SN1735 CF:CD:27:79:55:6B (unknown) CF:CD:27:79:55:6B FR:R20:SN1735 ... [ctrl] + [c] # sudo gatttool -t random -b CF:CD:27:79:55:6B -I D:27:79:55:6B][LE]> connect Attempting to connect to CF:CD:27:79:55:6B Error: connect to CF:CD:27:79:55:6B: Device or resource busy (16) # sudo hciconfig hci0 reset # sudo gatttool -t random -b CF:CD:27:79:55:6B -I [CF:CD:27:79:55:6B][LE]> connect Attempting to connect to CF:CD:27:79:55:6B Connection successful [CF:CD:27:79:55:6B][LE]> primary attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x0009, end grp handle: 0x0011 uuid: 00001523-1212-efde-1523-785feabcd123 attr handle: 0x0012, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb [CF:CD:27:79:55:6B][LE]> char-desc handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0009, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x000a, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x000b, uuid: 00001524-1212-efde-1523-785feabcd123 handle: 0x000c, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x000d, uuid: 00001525-1212-efde-1523-785feabcd123 handle: 0x000e, uuid: 00002902-0000-1000-8000-00805f9b34fb handle: 0x000f, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0010, uuid: 00001526-1212-efde-1523-785feabcd123 handle: 0x0011, uuid: 00002902-0000-1000-8000-00805f9b34fb handle: 0x0012, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x0013, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0014, uuid: 00002a29-0000-1000-8000-00805f9b34fb [CF:CD:27:79:55:6B][LE]> ... [ctrl] + [d] ``` # programming ``` sudo apt install python3 python3-pip build-essential libbluetooth-dev # pybluez requires libbluetooth-dev : pip install pybluez # pybluez does not support ble, use BLE_GATT instead pip install BLE_GATT # BLE_GATT has a problem with notifications, check out either bluepy or bleak ``` # troubleshooting 2021 December 2 I found that sometimes, after a boot, the service will be running, bluetooth is displayed via lsusb, but bluetoothctl run by the service sees no devices. I updated the service to run after bluetooth is available and have not seen the issue since. This DOES NOT show that the problem is fixed, as at the time of discovery was after bluetooth had initialized. Rather than research this issue a stab in the dark is what we have. 2021 December 14 After a boot last night we found that this did not work, again lsusb shows the device, bluetoothctl does not show devices, either run manually or from the radon-eye services. This means that the service either does not run after bluetooth or waiting does not work. the problem looks like this ``` $ lsusb Bus 001 Device 005: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) Bus 001 Device 003: ID 0424:ec00 Microchip Technology, Inc. (formerly SMSC) SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Microchip Technology, Inc. (formerly SMSC) SMC9514 Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub $ bluetoothctl Agent registered [bluetooth]# scan on No default controller available ``` I think I am going to test moving the systemd `After` and new `Requires` to the `radon-eye@.service` and see if that helps Other info I collected, `bluetoothd` was active running process, `rfkill list all` shows all bluetooth non-blocked OKay found something ``` $ hciconfig list hci0: Type: Primary Bus: USB BD Address: 00:1A:7D:DA:71:15 ACL MTU: 310:10 SCO MTU: 64:8 DOWN RX bytes:351 acl:0 sco:0 events:11 errors:0 TX bytes:33 acl:0 sco:0 commands:11 errors:0 ``` looks like the bluetooth adapter `hci0` is shown as `DOWN` looking at dmesg shows these logs ``` Bluetooth: hci0: unexpected event for opcode 0x0000 Bluetooth: hci0: command 0x0c14 tx timeout Bluetooth: hci0: command 0x0c25 tx timeout Bluetooth: hci0: command 0x0c38 tx timeout Bluetooth: hci0: unexpected event for opcode 0x0c14 ``` using `hciconfig hci0 up` does make device `UP` but bluetoothctl still does not see devices, another recommendation is: ``` $ sudo btmgmt power off Set Powered for hci0 failed with status 0x11 (Invalid Index) $ sudo btmgmt power on Set Powered for hci0 failed with status 0x11 (Invalid Index) ``` I got nowhere, did a reboot And another completely unrelated issue just popped up, yay! ``` $ bluetoothctl Agent registered [bluetooth]# scan on Failed to start discovery: org.bluez.Error.NotReady ``` for this issue I just issued a power off, then a power on, this helped this issue was started around the time I added the check for bluetoothctl reporting no default controller and me adding a subprocess.popen.communicate call that might have resulted in ``` Dec 14 22:39:46 solar-aquarium python3[1336]: tried to closed subprocess stdin but got error: argument should be integer or bytes-like object, not 'str' ``` 2021 Dec 19th More problems, last night I tried to add WiFi accesspoint via USB to the rpi running this project. It was connected to two radoneye devices but around 18:00 it stopped communicating with both of them. I did spill some tea in the living room and Emma sa moving stuff around, but I think that happened at 23:00. At 18:00 I think wesley arrived and we had either ordered pizza or were waiting for it to be made so I do not think I was doing anything. Anyways, running `bluetoothctl` right now with `scan on` does nothing. `$ hciconfig list hci0: Type: Primary Bus: USB BD Address: 00:1A:7D:DA:71:15 ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING INQUIRY RX bytes:13550 acl:101 sco:0 events:1405 errors:0 TX bytes:11588 acl:101 sco:0 commands:1212 errors:0 $ hcitool -i hci0 lescan LE Scan ... CF:CD:27:79:55:6B FR:R20:SN1735 CF:CD:27:79:55:6B (unknown) Disable scan failed: Input/output error ``` Okay, this is weird, after issuing the `hcitool` low energy scan, it looks like bluetoothctl started working. I am starting to suspect that even though `hcitool` and `hciconfig` are not recommended that they handle certain failures where `dbus` and `bluetoothctl` do not. The `rd200.py` process was logging the same error while the above was happeneing ``` Dec 19 14:56:00 solar-aquarium python3[461]: device not found, retrying in a second... Dec 19 14:56:00 solar-aquarium python3[461]: device not found, retrying in a second... Dec 19 14:56:00 solar-aquarium python3[461]: device not found, retrying in a second... Dec 19 14:56:00 solar-aquarium python3[461]: device not found, retrying in a second... ``` 2021 December 24 rebooted last night, this morning bluetoothctl and hcitool lescan both show no device found, dmesg shows errors: ``` Bluetooth: HCI device and connection manager initialized Bluetooth: HCI socket layer initialized Bluetooth: L2CAP socket layer initialized Bluetooth: SCO socket layer initialized usbcore: registered new interface driver btusb Bluetooth: hci0: unexpected event for opcode 0x0000 Bluetooth: hci0: command 0x1001 tx timeout Bluetooth: BNEP (Ethernet Emulation) ver 1.3 Bluetooth: BNEP filters: protocol multicast Bluetooth: hci0: CSR: Local version failed (-110) Bluetooth: BNEP socket layer initialized ``` decided to try to automate unplugging and replugging the bluetooth usb device using mvp/uhubctl on rpi. install pre-packaged, `apt install uhubctl` then modify permissions on the usb hub using `udev` rules. example udev rule is stored in `backend/52-usb.rules`. It allows anyone in the `dialout` group to power cycle the usb hub. `sudo usermod -aG dialout radon`, copy the script over to `/etc/udev/rules.d/` and reload udev rules, `sudo udevadm trigger --attr-match=subsystem=usb` at first I did not get permissons to work I was going to try to reboot, but before I did, testing command worked to fix bluetooth: ``` # on rpi B+,2B,3B ports 2,3,4,5 are ganged so even if bluetooth is plugged into port 4 you need to hit port 2 # action 2 is cylcle power, port 1 is ethernet/wifi, on pi 3b+ ports are different sudo uhubctl --location=1-1 --port=2 --action=2 ``` reboot did get the group thing working, so now it is just a thing to decide when to issue the above command, it seems somewhat risky with two rd200.py running 2022 Jan 19th a couple more issues we can get into a state ``` [bluetooth]# scan on Failed to start discovery: org.bluez.Error.InProgress [bluetooth]# scan off Failed to stop discovery: org.bluez.Error.Failed [bluetooth]# exit ``` I was working on this issue and found that one of the rd200.py processes looks like it hung after restarting `rd200.py` does not detect this issue a solution that seemed to work was just running `bluetoothctl power off` then `bluetoothctl power on` this is a bit of an issue as doing this in two processes is going to be an issue. I am not even sure why this issue cropped up. do something like: ``` import time import os import errno # handle org.bluez.Error.InProgress try: # use a file as a lock (exclusive create) f=open('someFile', mode='x') ble_ctl(addr:str, retry = 50, powerCycle = True) # delete the file f.close() os.remove('someFile') except Exception as e: if(errno.EEXIST == e.errno): # make sure the file lock is not broken try: old=os.stat('someFile') if(60 < (int(time.time()) - int(old.st_mtime))): print("someFile lock was borked, cleaning up") os.remove('someFile') except Exception as e2: print("failed to cleanup borked someFile lock", e2) else: print("unexpected error while dealing with org.bluez.Error.InProgress", e) ``` 2022 Feb 20 only the bedroom device was connected and the basement was not. strace on the process for the basement shows that it was doing a read write and select with, I think a 500ms timeout. It looked like it was looping and not doing anything. Log just shows a message about `failed to cleanup BLE_GATT objects because...` and nothing eles. I logged into the `bluetoothctl` interface and issued the `connect AA:BB:CC:DD:EE:FF` command and exited and the process went back to normal. I think there is an exception not being raised and causing the loop to fail. I should probably do something about this, but I cannot really find where in the code the problem is occurring. 2022 Jun 03 Looks like it stopped, uptime is 3 days, programs are running but cannot get out of an issue where: ``` [bluetooth]# connect C2:58:00:9A:26:29 Attempting to connect to C2:58:00:9A:26:29 Failed to connect: org.bluez.Error.Failed [bluetooth]# scan off Failed to stop discovery: org.bluez.Error.Failed ``` `bluetoothctl` shows activity, neighbors samsung TV, etc, but interacting, using connect, etc just gives `org.bluez.Error.Failed` messages. I issued the `bluetoothctl power off`, waited a couple seconds, `bluetoothctl power on` This did something but did not fix bluetooth, i noticed the other process was repeating every half second in strace: ``` _newselect(0, NULL, NULL, NULL, {tv_sec=0, tv_usec=500000}) = 0 (Timeout) eventfd2(0, EFD_CLOEXEC|EFD_NONBLOCK) = 7 write(7, "\1\0\0\0\0\0\0\0", 8) = 8 write(6, "\1\0\0\0\0\0\0\0", 8) = 8 futex(0x1ac6c70, FUTEX_WAKE_PRIVATE, 1) = 1 futex(0x1ac6b9c, FUTEX_WAKE_PRIVATE, 1) = 1 futex(0x1ac303c, FUTEX_WAKE_PRIVATE, 1) = 1 poll([{fd=7, events=POLLIN}], 1, 0) = 1 ([{fd=7, revents=POLLIN}]) read(7, "\2\0\0\0\0\0\0\0", 16) = 8 write(7, "\1\0\0\0\0\0\0\0", 8) = 8 futex(0x1ae8604, FUTEX_WAKE_PRIVATE, 2147483647) = 0 close(7) = 0 clock_gettime64(CLOCK_MONOTONIC, {tv_sec=328018, tv_nsec=340560669}) = 0 _newselect(0, NULL, NULL, NULL, {tv_sec=0, tv_usec=500000}) = 0 (Timeout) eventfd2(0, EFD_CLOEXEC|EFD_NONBLOCK) = 7 write(7, "\1\0\0\0\0\0\0\0", 8) = 8 write(6, "\1\0\0\0\0\0\0\0", 8) = 8 futex(0x1ac6c70, FUTEX_WAKE_PRIVATE, 1) = 1 futex(0x1ac6b9c, FUTEX_WAKE_PRIVATE, 1) = 1 futex(0x1ac303c, FUTEX_WAKE_PRIVATE, 1) = 1 poll([{fd=7, events=POLLIN}], 1, -1) = 1 ([{fd=7, revents=POLLIN}]) read(7, "\1\0\0\0\0\0\0\0", 16) = 8 futex(0x1ae85f8, FUTEX_WAKE_PRIVATE, 1) = 1 poll([{fd=7, events=POLLIN}], 1, 0) = 1 ([{fd=7, revents=POLLIN}]) read(7, "\1\0\0\0\0\0\0\0", 16) = 8 write(7, "\1\0\0\0\0\0\0\0", 8) = 8 futex(0x1ae8604, FUTEX_WAKE_PRIVATE, 2147483647) = 0 close(7) = 0 clock_gettime64(CLOCK_MONOTONIC, {tv_sec=328018, tv_nsec=899447448}) = 0 ``` ## python BLE_GATT trouble - ModuleNotFoundError: No module named 'gi' internet says it is PyGObject introspection, bindings to support GTK+ 3 and GNOME ``` # install PyGObject bindings sudo apt install python3-gi ``` ## BLE info UUID is 128-bit value representing a unique characteristic, for example, `00002A00-0000-1000-8000-00805F9B34FB` is the "Device Name Characteristic". Address is a 6-octect MAC (48-bit) number unique to every device. data from BLE is little endian GATT is Generic Attribute Profile BLE peripherals can only be connected to one central device at a time Bluetooth base UUID address is 0000xxxx-0000-1000-8000-00805f9b34fb, the Device Name Characteristic is sometimes shortened to just 0x2A00. ## RadonEye BLE interface someone posted a dump of their work sniffing traffic on the official Android app and found that sending 0x50 to the characteristic 00001524-1212-efde-1523-785feabcd123 returns a 20 byte field back where the 3rd to 6th bytes are big-endian formatted IEEE754 representation of a floating point value of the Radon level in picocuries per liter -- the response is written to 00001525 ... characteristic. ### some deception The advertisement claims 30 readings per hour but then they mention that the first value is available after 10 minutes. It would seem that they take five readings and then update the display. The data on the display is the only externally accessible data so we are only going to see a maximum of six readings an hour. Nyquist sampling says that we have got to sample twice so we should be sampling twelve times an hour. ### Generic Access attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb ### Generic Attribute attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb ### LED Button Service attr handle: 0x0009, end grp handle: 0x0011 uuid: 00001523-1212-efde-1523-785feabcd123 ### Device Information attr handle: 0x0012, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb ## LED Button Service (LBS) (official BLE documentation) The GATT LED Button Service (LBS) is a custom service that receives information about the state of an LED and sends notifications when a button changes its state. ### Service UUID The 128-bit vendor specific service UUID is 00001523-1212-EFDE-1523-785FEABCD123 ### Characteristics This service has to characteristics #### Button Characteristic 00001524-1212-EFDE-1523-785FEABCD123 ##### Notify Enable notifications for the Button Characteristic to receive button data from the application. ##### Read Read button data from the application #### Button Characteristic 00001525-1212-EFDE-1523-785FEABCD123 ##### Write Write data to theLED Characteristic to change the LED state