Onlangs was ik toe aan een nieuwe horloge. Nog geen smartwatch, maar wel een multifunctioneel horloge gekocht, een Nokia Steel. Zoals een smartwatch, moet je de Nokia Steel configureren via een smartphone. Dit ging verschrikkelijk moeizaam, het duurde namelijk een eeuwigheid voor de smartphone en het horloge gekoppeld waren en een verbinding tot stand kwam.
Aangezien de smartphone en het horloge via bluetooth communiceren, moet je de bluetooth signalen ook via een computer kunnen scannen. Het Nokia Steel horloge gebruikt een nogal vreemd bluetoothgedrag. Het maakt zich namelijk bekend met steeds andere mac-adressen. Met de opdracht bluetoothctl kan je bluetooth-apparaten als volgt scannen:
dany@main:~>bluetoothctl
[NEW] Controller 7C:67:A2:C1:F8:F8 main.pindanet.home [default] [bluetooth]#scan on
Discovery started [CHG] Controller 7C:67:A2:C1:F8:F8 Discovering: yes [NEW] Device 1A:73:83:5E:0C:CE Activite C8 [CHG] Device 1A:73:83:5E:0C:CE RSSI: -68 [bluetooth]#scan off
[CHG] Device 1A:73:83:5E:0C:CE RSSI is nil [CHG] Controller 7C:67:A2:C1:F8:F8 Discovering: no Discovery stopped [bluetooth]#remove 1A:73:83:5E:0C:CE
[DEL] Device 1A:73:83:5E:0C:CE Activite C8 Device has been removed [bluetooth]#exit
[DEL] Controller 7C:67:A2:C1:F8:F8 main.pindanet.home [default]
De NEW regels tonen de opgemerkte bluetooth apparaten, waarbij de eerste NEW regel de computer is waarop bluetoothctl gestart is.
Via de blauwe bluetooth-prompt kan je bluetoothctl opdrachten ingeven en uitvoeren.
Met de scan on
opdracht start je het opsporen van bluetooth-apparaten.
De CHG regels tonen veranderende eigenschappen van reeds opgemerkte bluetooth apparaten. Bijvoorbeeld het in de scan mode zetten van de bluetooth interface waardoor andere bluetooth apparaten opgemerkt worden.
Bij het opmerken van een nieuw bluetooth apparaat (NEW regel) wordt het mac adres en de naam van het apparaat weergegeven. Mijn Nokia Steel horloge wordt hierboven opgemerkt met het mac adres 1A:73:83:5E:0C:CE en de naam Activite C8.
Met de opdracht scan off
stop je het scannen naar bluetooth apparaten.
Met de opdracht remove verwijder je een bluetooth apparaat met een specifiek mac adres uit de lijst met gekende bluetooth apparaten.
Met de exit
opdracht sluit je de bluetoothctl af.
De afbeelding hiernaast toont duidelijk dat bij een volgende scan wat later het mac adres van het Nokia Steel horloge is verandert.
Ondanks dit wat eigenaardige gedrag kan je het Steel Nokia horloge toch gebruiken om de aanwezigheid van een drager te detecteren. Bijvoorbeeld om in te loggen, domoticasystemen, of gewoon omdat het leuk is. Het volgende script verwezenlijkt zoiets:
#!/bin/bash # Het bestand absent bevat het aantal keer het horloge niet werdt opgemerkt absent=$(cat absent) # Aantal keer niet opgemerkt wordt verhoogt ((absent++)) # Voer een bluetooth scan uit en sla de resultaten op in het bestand bluetoothscan.txt (sleep 1; echo "scan on"; sleep 50; echo "exit") | bluetoothctl > bluetoothscan.txt # Teller voor het aantal nieuwe bluetooth apparaten maccounter=0 # Analyseer regel per regel de bluetooth scan resultaten while read line do # Met welke soort regel hebben we te maken var2=$(awk '{ print $2 }' <<< "$line") # We zijn enkel geïnteresseerd in NEW regels testvar=$(echo -e '\015\033[K[\033[0;92mNEW\033[0m]') # Kleurcodes zichtbaar maken # echo "$var2" | hexdump -C -b # Analyseer enkel de NEW regels if [ "$var2" == "$testvar" ]; then # Bepaal het mac adres van het gevonden bluetooth apparaat mac=$(awk '{ print $4 }' <<< "$line") # Bepaal de naam van het gevonden bluetooth apparaat name=$(awk '{ print $5 " " $6 }' <<< "$line") # Indien er geen naam werd ontvangen, wordt nogmaals het mac adres vermeld namemac=$(awk '{ print $5 }' <<< "$line") # Het Nokia Steel horloge werd opgemerkt if [ "$name" == "Activite C8" ] || [ "$namemac" == "$mac" ]; then # Sla het mac adres van het Nokia Steel horloge op mac[$maccounter]=$mac # Verhoog de teller voor het volgende Nokia Steel mac adres ((maccounter++)) # Het Nokia Steel horloge is in de buurt absent="0" fi fi done < bluetoothscan.txt # Verwijder alle Nokia Steel mac adressen uit de gevonden apparaten lijst for i in "${mac[@]}" do (sleep 1; echo "remove $i"; sleep 1; echo "exit") | bluetoothctl done # Sla het opeenvolgend aantal keer dat de Steel Nokia horloge niet werd gevonden op echo $absent > absent # Hieronder kan je absent testen (bijvoorbeeld groter dan 5 opeenvolgende keren niet gevonden) # en op basis daarvan een actie starten
Via het pipen (|) van een aantal opdrachten gescheiden door punt komma's en tussen haken kan je opdrachten in bluetoothctl laten uitvoeren. De haken zorgen ervoor dat de opdrachten ertussen parallel worden uitgevoerd (gelijktijdig met het uitvoeren van bluetoothctl). De eerste sleep opdracht zorgt voor een wachttijd van 1 seconde, tijd genoeg om de bluetoothctl opdracht parallel te starten. Daarna wordt de scan opdracht 50 seconden uitgevoerd en wordt bluetoothctl afgesloten.
Meestal meldt het Nokia Steel horloge zich binnen deze 50 seconden. Maar soms ook niet. Start dus nooit geen niet aanwezig actie bij een enkele niet aanwezig melding (absent = 1). Bij mij wordt de afwezig actie pas bij 5 opeenvolgende niet aanwezig meldingen gestart (absent > 5). Je kunt de scan natuurlijk verlengen, maar dit heeft als nadeel dat de reactietijden op aanwezigheid (absent = 0) dan te traag wordt.
Het Nokia Steel horloge meld zich via bluetooth soms aan zonder naam, de naam wordt dan later via een CHG regel toegekend. Vandaar de || (Or) in de if test.
Op een Raspberry Pi in mijn bureau wordt elke minuut de scan uitgevoerd. Bij aanwezigheid wordt het touchscreen actief, bij afwezigheid wordt het touch screen donker. Om het script elke minuut uit te voeren, gebruik ik een systemd timer. Dit bestaat uit twee bestanden, /etc/systemd/system/PindaNetBluetoothScan.service:
[Unit] Description=Bluetooth Detection Scan [Service] Type=simple ExecStart=/usr/sbin/bluetoothscan.sh
En /etc/systemd/system/PindaNetBluetoothScan.timer:
[Unit] Description=Bluetooth Detection Scan [Timer] OnBootSec=1min OnUnitActiveSec=1min Unit=PindaNetBluetoothScan.service [Install] WantedBy=multi-user.target
Het aangepaste script /usr/sbin/bluetoothscan.sh:
#!/bin/bash absent=$(cat /var/www/html/data/absent) ((absent++)) (sleep 1; echo "scan on"; sleep 50; echo "exit") | bluetoothctl > /var/www/html/data/bluetoothscan.txt maccounter=0 while read line do var2=$(awk '{ print $3 }' <<< "$line") testvar=$(echo -e '\015[\033[0;92mNEW\033[0m]') # echo "$var2" | hexdump -C -b >> /var/www/html/data/bluetoothscandebug.txt if [ "$var2" == "$testvar" ]; then mac=$(awk '{ print $5 }' <<< "$line") name=$(awk '{ print $6 " " $7 }' <<< "$line") namemac=$(awk '{ print $6 }' <<< "$line") if [ "$name" == "Activite C8" ] || [ "$namemac" == "$mac" ]; then mac[$maccounter]=$mac ((maccounter++)) absent="0" fi fi done < /var/www/html/data/bluetoothscan.txt for i in "${mac[@]}" do (sleep 1; echo "remove $i"; sleep 1; echo "exit") | bluetoothctl done echo $absent > /var/www/html/data/absent # Logboek aanvullen, vergeet niet regelmatig op te ruimen (rotate) if [ "$absent" -gt "0" ]; then echo "Afwezig($absent) op $(date)" >> /var/www/html/data/bluetoothscandebug.txt else echo "Thuis($absent) op $(date)" >> /var/www/html/data/bluetoothscandebug.txt fi if [ "$absent" -eq "0" ]; then # home # activate touchscreen and status led's echo 0 > /sys/class/backlight/rpi_backlight/bl_power echo 255 > /sys/class/leds/led0/brightness echo 255 > /sys/class/leds/led1/brightness exit fi if [ "$absent" -gt "5" ]; then # not home # deactivate touchscreen and status led's echo 1 > /sys/class/backlight/rpi_backlight/bl_power echo 0 > /sys/class/leds/led0/brightness echo 0 > /sys/class/leds/led1/brightness fi
Let op het analyseren van de bluetoothscanctl regels. De gegevensposities zijn een plaats opgeschoven. Ook testvar, de manier waarop NEW weergegeven wordt, is verschillend. Blijkbaar is de uitvoer van de bluetoothctl uitvoer in systemd verschillend van deze in een klassieke terminal. Zit hier het gebruik van kleur voor iets tussen? Of gebruikt systemd anderen instellingen?
Maak het script uitvoerbaar met:
sudo chmod +x /usr/sbin/bluetoothscan.sh
Breng systemd op de hoogte van de aanpassingen:
sudo systemctl daemon-reload
Zorg dat de systemd timer bij het starten van de Raspberry Pi automatisch start:
sudo systemctl enable PindaNetBluetoothScan.timer
Start de systemd timer manueel, dus zonder complete herstart:
sudo systemctl start PindaNetBluetoothScan.timer
Bekijk de systemd timers:
systemctl list-timers
Bekijk of de systemd timer nog actief is:
sudo systemctl status PindaNetBluetoothScan.timer