Sunday 21 January 2018

Raspberry Pi Zero W as IoT Bluetooth Gateway Part2: Replacing the Laptop

Raspberry Pi Zero W as Bluetooth IoT Gateway installed in the front porch
The original Bluetooth Autogate Remote used a recycled Acer Aspire F15 laptop as an IoT gateway. The laptop ran an Apache webserver for the html/php program. This went very well until a fortnight ago when we had a cool rainy spell and the garden got waterlogged, which always seem to affect wireless communications at the Autogate control box located in the gatepost.

The Bluetooth Autogate Remote started to fail, first on individual button presses, then the laptop bluetooth controller lost the link to the HC-06 in the gatepost. A typical bluetoothctl command sequence and output now goes something like this:

[bluetooth]# scan on
Discovery started
[CHG] Controller C8:FF:28:27:7D:2C Discovering: yes
[CHG] Device 98:D3:32:20:BB:7B RSSI: -90
[bluetooth]# devices
Device 98:D3:32:20:BB:7B HC-06
[bluetooth]# pair 98:D3:32:20:BB:7B
Attempting to pair with 98:D3:32:20:BB:7B
Failed to pair: org.bluez.Error.ConnectionAttemptFailed

When RSSI value got to about -86 the pairing would work but dropped every few days or so. This handy link explained quite well that RSSI meant 'Received Signal Strength Indicator' and has an RSSI table:

Acceptable Signal Strengths

Signal StrengthTL;DRRequired for
-30 dBmAmazingMax achievable signal strength. The client can only be a few feet from the AP to achieve this. Not typical or desirable in the real world.N/A
-67 dBmVery GoodMinimum signal strength for applications that require very reliable, timely delivery of data packets.VoIP/VoWiFi, streaming video
-70 dBmOkayMinimum signal strength for reliable packet delivery.Email, web
-80 dBmNot GoodMinimum signal strength for basic connectivity. Packet delivery may be unreliable.N/A
-90 dBmUnusableApproaching or drowning in the noise floor. Any functionality is highly unlikely.N/A

So my RSSI went from 'Not Good' to 'Unusable'. Now the laptop's bluetooth controller had 2 walls and a plastic enclosure between it and the Autogate Bluetooth HC-06, so I though it might be a good idea to have the IoT Gateway on the front porch, which not only is only 30m away but had line-of-sight to the HC-06.

That was the purpose of the Raspberry Pi Zero W. My last post showed Slackware 14.1 can run on it. This is handy because my laptop ran Slackware 14.2.

First I need to get the WiFi running on the Raspberry Pi Zero W. That was easy enough. It turned out I was missing some bios files:
-rwxr-xr-x 1 root root     6551 Oct 30 18:36 fixup.dat
-rwxr-xr-x 1 root root     2578 Oct 30 18:36 fixup_cd.dat
-rwxr-xr-x 1 root root     9694 Oct 30 18:36 fixup_db.dat
-rwxr-xr-x 1 root root     9694 Oct 30 18:36 fixup_x.dat
-rwxr-xr-x 1 root root  2820196 Oct 30 18:36 start.elf
-rwxr-xr-x 1 root root   667460 Oct 30 18:36 start_cd.elf
-rwxr-xr-x 1 root root  4956676 Oct 30 18:36 start_db.elf
-rwxr-xr-x 1 root root  3904228 Oct 30 18:36 start_x.elf

These files were really a set (startup.elf needed fixup.dat and so on) and in my case I had start.elf but not fixup.dat. In addition I was missing the file:
-rwxr-xr-x 1 root root    15830 Oct 30 18:36 bcm2708-rpi-0-w.dtb

Once corrected the WiFi interface came up and was connected to my home WiFi hotspot with no fuss. I could now ssh into the Zero W and use it without the monitor or USB keyboard. 

The bluetooth controller was a whole different ballgame. After spending a whole Sunday on it, I gave up and decided to use a Vztech bluetooth dongle instead. This I connected to the micro USB OTG connector and worked straight out of the box.

The bluetooth software was the same Bluez used in Slackware 14.2, but being the 14.1 version did not have bluetoothctl. The function I missed most was the bluetooth agent required to pair the HC-06 to the Pi Zero W. Happily a little digging showed that Bluez tarball for Slackware 14.1 has a workable agent, simple-agent which was built but not included when the Slackware upgradepkg program installed Bluez.

I just needed to unpack the tarball and install it:

root@rpi-0-w:~# cp  /tmp/bluez-4.99/test/simple-agent /usr/bin/

Now without bluetoothctl the commands are a little different but still quite straightforward:

root@rpi-0-w:~# chmod +x /etc/rc.d/rc.bluetooth

Reboot, taking care to first plug in the bluetooth dongle, then do:
root@rpi-0-w:~# hcitool dev
Devices:
        hci0    00:1A:7D:DA:71:13

And more important:
root@rpi-0-w:~# hciconfig
hci0:   Type: BR/EDR  Bus: USB
        BD Address: 00:1A:7D:DA:71:13  ACL MTU: 310:10  SCO MTU: 64:8
        DOWN
        RX bytes:574 acl:0 sco:0 events:30 errors:0
        TX bytes:368 acl:0 sco:0 commands:30 errors:0

root@rpi-0-w:~# hciconfig hci0 up

And now the bluetooth controller is running:

root@rpi-0-w:~# hciconfig hci0
hci0:   Type: BR/EDR  Bus: USB
        BD Address: 00:1A:7D:DA:71:13  ACL MTU: 310:10  SCO MTU: 64:8
        UP RUNNING
        RX bytes:1148 acl:0 sco:0 events:60 errors:0
        TX bytes:736 acl:0 sco:0 commands:60 errors:0

Next you need to find the bluetooth channel:

root@rpi-0-w:~# sdptool browse local

Which produced output like this (look for RFCOMM):

Service Name: Dial-Up Networking
Service RecHandle: 0x10005
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100

Which means we are channel 1. We then look for the HC-06:

root@rpi-0-w:~# hcitool scan
Scanning ...
        98:D3:32:20:BB:7B       HC-06

Next we launch the bluetooth agent:

root@rpi-0-w:~simple-agent hci0 98:D3:32:20:BB:7B
RequestPinCode (/org/bluez/481/hci0/dev_98_D3_32_20_BB_7B)
Enter PIN Code: 1234
Release
New device (/org/bluez/481/hci0/dev_98_D3_32_20_BB_7B)

The last step is then:

root@rpi-0-w:~/bluez# rfcomm bind /dev/rfcomm0 98:D3:32:20:BB:7B 1

And the all-important RSSI is now in 'Amazing' category:

root@rpi-0-w:~# hcitool rssi 98:D3:32:20:BB:7B
RSSI return value: -19

The next steps involve setting up python, pymodbus and apache in Slackware 14.1, and are best treated separately. You can also refer to other online links for this. The end result is much the same as the previous post, and worked about the same. Not bad for the RM42 Raspberry Pi Zero W, which replaced an RM3,200 Acer AspireF15 as the IoT Bluetooth Gateway.

Now all this seemed a little fly-by-the-seat-of-your-pants, but this is the nature of DevOps/Rapid Development. It is iterative and relies on incremental redesigns with the emphasis on putting out the prototype as quickly as possible. Notice it took a few weeks operating the prototype for the bluetooth wireless problem to be obvious. 

Some problems are immediately obvious: the Pi Zero W does not have battery backup while the laptop did. Installing a battery would require other things: a proper enclosure, perhaps a shelf. But in the meantime up goes the latest prototype to fish for other problems. 

Perhaps one of the most important things about Rapid Development is customer involvement. One indication the project is going well is the wife got quite used to opening the autogate from her car, and complained immediately when the Bluetooth Autogate stopped working in wet weather.   

Happy Trails.

Update: as feared, every few days or so the Raspberry Pi Zero W rebooted by itself. This was tracked by having the pymodbus server program print out regular heatbeat messages:

 Cmd z, voltages are [3, 255, 2, 157]
stored values= [3, 252, 2, 154]
address= 0  answer:  [3, 255, 2, 157]      
CPU 1023 Battery 669
CPU 5.00 Battery 13.88 Volts 2018-01-26 04:34:13
Reply: ÿHCM¡LJP len 10                              

 Cmd z, voltages are [3, 255, 2, 161]
stored values= [3, 255, 2, 157]  
address= 0  answer:  [3, 255, 2, 161]
CPU 1023 Battery 673
CPU 5.00 Battery 13.97 Volts 2018-01-26 04:46:14                              
Reply: ïHCMLJP len 10    

 Cmd z, voltages are [3, 239, 2, 156]
stored values= [3, 255, 2, 161]
address= 0  answer:  [3, 239, 2, 156]
CPU 1007 Battery 668  
CPU 4.92 Battery 13.86 Volts 2018-01-26 04:58:15
packet_write_wait: Connection to 172.16.1.25 port 22: Broken pipe

We had gotten really used to that WiFi autogate remote, so to keep it going (while I am trying to figure out what went wrong) I simply added this to /etc/rc.d/rc.local so that the IoT gateway program restarted itself. Not using bluetoothctl had a silver lining after all:

echo "1234" | simple-agent hci0 98:D3:32:20:BB:7B release
rfcomm bind 0 98:D3:32:20:BB:7B 1
sleep 2
python ./autogate_server.py > /dev/null &

No comments:

Post a Comment