AWS SSM Agent on an RPi 4

So as part of the work I do with AWS DeepRacer I use SSM Agent on the cars and (finally) now also on the Raspberry Pi based timing system, to make things easier I thought I’d “quickly” install and activate SSM on the RPi so I can access them remotely and show the timer online as part of DeepRacer Event Manager (DREM – more on which in another blog post)

Installing SSM on a 32bit OS on an RPi Zero or 4 was easy, just works, however on a 64bit OS I was getting errors:

dpkg: dependency problems prevent configuration of amazon-ssm-agent:armhf:
 amazon-ssm-agent:armhf depends on libc6.

dpkg: error processing package amazon-ssm-agent:armhf (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 amazon-ssm-agent:armhf

Took me a while to find the answer as I didn’t happen to have the time to get an uninterrupted run at fixing the issue and more importantly testing the fix (because I was activating SSM as part of a scripted process) each attempt meant I needed to re-install the OS on the RPi to ensure it was working correctly.

Anyway, the solution was to install libc6:armhf so now my code to install SSM on an RPi 4 running 64bit OS is as follows:

sudo dpkg --add-architecture armhf
sudo apt-get update
sudo apt-get install -y libc6:armhf

mkdir /tmp/ssm
sudo curl https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_arm/amazon-ssm-agent.deb -o /tmp/ssm/amazon-ssm-agent.deb
dpkg -i /tmp/ssm/amazon-ssm-agent.deb
rm -rf /tmp/ssm

And once installed activate SSM as normal.

Hopefully this helps someone, and if not it will probably help future me.

Pi + Bluetooth = Is the track boss going to have a heart attack

So I had an idea that fell out of being Track Boss at re:Invent for a few hours each day during the DeepRacer championship. Wouldn’t it be interesting to see what the heart rate and step count of the track boss was….?

So quick bit of DuckDuckGo(ing) later and I had a Polar H10 on the way and was looking at how I could get going – this post on RepRage formed the basis of some early work.

So I was able to scan for my device:

$ sudo hcitool lescan
 LE Scan …
 F4:DF:3F:95:DE:EA (unknown)
 F4:DF:3F:95:DE:EA Polar H10 65AAF325

But trying to connect to it failed using hcitool, so I switched to using gatttool with success (connection and data):

$ gatttool -t random -b F4:DF:3F:95:DE:EA -I
 [F4:DF:3F:95:DE:EA][LE]> connect
 Attempting to connect to F4:DF:3F:95:DE:EA
 Connection successful
 [F4:DF:3F:95:DE:EA][LE]> characteristics
 handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
 handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
 handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
 handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002aa6-0000-1000-8000-00805f9b34fb
 handle: 0x000b, char properties: 0x20, char value handle: 0x000c, uuid: 00002a05-0000-1000-8000-00805f9b34fb

So that’s some information from the strap, now to subscribe to notifications to get the heart rate data:

 [F4:DF:3F:95:DE:EA][LE]> char-write-req 0x0011 0100
 Characteristic value was written successfully
 Notification handle = 0x0010 value: 10 40 e4 03 
 Notification handle = 0x0010 value: 10 40 92 03 
 Notification handle = 0x0010 value: 10 40 7e 03 
 Notification handle = 0x0010 value: 10 41 8f 03 76 03

For me I get ~79 notifications before an error, however for now getting something back is better than nothing especially given the second “value” is the important one, my heart rate in hexadecimal. So we can (sort of) read the data from the strap, now to do this in code.

Python is my current go to language so it was time to add some libraries and see what we could get working:

$ sudo apt-get install -y python3 python3-pip libglib2.0-dev
$ sudo pip3 install bluepy

Adding in MQTT and python libraries so the data can be used in a presentation layer:

$ sudo apt-get install -y mosquitto mosquitto-clients
$ sudo systemctl enable mosquitto.service
$ sudo pip3 install argparse paho-mqtt

My code is still bombing out with a connection error though after 147 notifications from bluepy. On the up side I’m not the only hitting this issue, on the down side there doesn’t appear to be a decent fix. For me running:

$ hcitool con
Connections:
         < LE F4:DF:3F:95:DE:EA handle 64 state 1 lm MASTER 

To find out the connection handle (in this case 64) followed by:

$ sudo hcitool lecup --handle 64 --min 250 --max 400 --latency 0 --timeout 600

Fixes the problem (todo: make this happen using magic)

So with the code below:

import datetime
import bluepy.btle as btle
import paho.mqtt.client as mqtt
import argparse
import json

packets = 0

class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        btle.DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        global packets 
        packets += 1

        global hr
        hr = str(data[1])

        global time
        time = datetime.datetime.now().time()
        print("time: {} packet: {} Handle: {} HR (bpm): {}".format(time, packets, cHandle, data[1]))

parser = argparse.ArgumentParser(description="Connect to Polar H10 HRM")
parser.add_argument('device', type=str, help='HRM strap device ID')

args = parser.parse_args()
print('args: {}'.format(args.device))

p = btle.Peripheral(args.device, addrType="random")
p.setDelegate(MyDelegate())

#start hr notification
service_uuid = 0x180D
svc = p.getServiceByUUID(service_uuid)
ch = svc.getCharacteristics()[0]
desc = ch.getDescriptors()[0]
desc.write(b"\x01\x00", True)

# MQTT
broker_url = "10.10.10.71"
broker_port = 1883

client = mqtt.Client()
client.connect(broker_url, broker_port)

# listen for notifications
while True:
    if p.waitForNotifications(1.0):
        payload = json.dumps({'time': str(time), 'heart_rate': hr})
        client.publish(topic="TrackBossHRM", payload=str(payload), qos=0, retain=False)
        continue

I have continuous heart rate data getting added into an MQTT based queue for use elsewhere…

$ mosquitto_sub -d -t TrackBossHRMClient mosqsub|2671-raspberryp sending CONNECT
 Client mosqsub|2671-raspberryp received CONNACK (0)
 Client mosqsub|2671-raspberryp sending SUBSCRIBE (Mid: 1, Topic: TrackBossHRM, QoS: 0)
 Client mosqsub|2671-raspberryp received SUBACK
 Subscribed (mid: 1): 0
 Client mosqsub|2671-raspberryp received PUBLISH (d0, q0, r0, m0, 'TrackBossHRM', … (47 bytes))
 {"time": "17:26:43.999799", "heart_rate": "72"}
 Client mosqsub|2671-raspberryp received PUBLISH (d0, q0, r0, m0, 'TrackBossHRM', … (47 bytes))
 {"time": "17:26:44.997310", "heart_rate": "72"}

Now to do something with it.