# 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
