Ble2mqtt: Unterschied zwischen den Versionen
Drhirn (Diskussion | Beiträge) |
Drhirn (Diskussion | Beiträge) K (Baustelle entfernt) |
||
Zeile 1: | Zeile 1: | ||
{{Infobox Modul | {{Infobox Modul | ||
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten | |ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten |
Version vom 9. November 2023, 11:24 Uhr
Ble2mqtt | |
---|---|
Zweck / Funktion | |
Anwesenheitserkennung von Bluetooth-Geräten | |
Allgemein | |
Typ | Utilities |
Details | |
Dokumentation | Thema |
Support (Forum) | Unterstützende Dienste |
Modulname | ble2mqtt |
Ersteller | PatrickR |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
ble2mqtt ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.
Es verwendet dazu die Linux Tools bluetoothctl und gatttool.
ble2mqtt ist in Perl geschrieben und wurde von PatrickR erstellt. Weitere Informationen finden sich in diesem Forums-Topic. Fragen dazu bitte in den Bereich Unterstützende Dienste
Voraussetzungen
- Debian od. Raspberry Pi OS
- Bluetooth Empfänger
Parameter
Beim Start von ble2mqtt können folgende Parameter angegeben werden:
Parameter | Beschreibung | Standardwert | Beispiel | Optional |
---|---|---|---|---|
--mqttserver | Die Adresse des MQTT Brokers inklusive Port | --mqttserver mqtt.example.org:1883 | nein | |
--mqttfingerprint | Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates | --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8 | ja | |
--mqtttopic | An welches MQTT-Topic das Tool die Informationen schicken soll. | ble2mqtt | --mqtttopic ble2mqtt/Wohnzimmer | ja |
--mqttuser | Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll | --mqttuser ble2mqtt | ja bzw. abhängig vom Broker | |
--mqttpass | Das zum Benutzernamen gehörende Passwort | --mqttpass verysecret3 | ja bzw. abhängig vom Broker | |
--retain | Versendet die Nachrichten present und lastseen als retained. | 0 | --retain | ja |
--daemonize | Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll | 0 | --daemonize | ja |
--loglevel | Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG. | LOG_INFO | --loglevel LOG_ERR | ja |
--logtarget | Wohin gelogged werden soll. Mögliche Optionen sind syslog und stdout. | syslog | --logtarget stdout | ja |
--absentinterval | Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30. | 60 | --absentinterval 120 | ja |
--rssithreshold | Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5. | 10 | --rssithreshold 8 | ja |
--watchdogthreshold | Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie. | 0 | --watchdogthreshold 30 | ja |
--debug | Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output. | 0 | --daemonize --debug 4 | ja |
--mac | Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert. | 77:88:99:00:AA:BB)' | ja | |
--batterymaxage | Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check. | 48 | --batterymaxage 6 | ja |
--forcebattery | Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird. | 0 | --forcebattery | ja |
Beispiele
- Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden
ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0
- Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt
ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac '(11:22:33:44:55:66|77:88:99:00:AA:BB)'
- Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben
ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain
Installation
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.
sudo cp -a ble2mqttd /usr/local/bin/
Danach das Script noch als ausführbar markieren
sudo chmod +x /usr/local/bin/ble2mqttd
Benötigte Linux Pakete
Die benötigten Pakete können ganz einfach mit apt installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.
sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl
Benötigte Perl-Module
Es wird das Modul Net::MQTT::Simple (libnet-mqtt-simple-perl) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels cpan installiert werden. Voraussetzung dafür ist das Modul CPAN::DistnameInfo, welches zuerst installiert werden muss.
sudo cpan CPAN::DistnameInfo sudo cpan Net::MQTT::Simple
Sobald libnet-mqtt-simple-perl verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.
Erster Test
Mit einem einfachen Aufruf von ble2mqtt kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.
sudo /usr/local/bin/ble2mqttd
Erstellen einens Systemd-Daemons
Damit ble2mqtt bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.
sudo nano /etc/systemd/system/ble2mqttd.service
[Unit]
Description=ble2mqttd
After=bluetooth.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac '(11:22:33:44:55:66|77:88:99:00:AA:BB)' --absentinterval 30 --mqttuser <username> --mqttpass <password>
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable ble2mqttd.service sudo systemctl start ble2mqttd.service
Einbindung in FHEM
Da ble2mqtt alle Informationen an einen MQTT-Broker sendet, können diese Informationen ganz einfach als MQTT2_DEVICE in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.
Anwesenheitserkennung mittels BT-Tags
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics. Für jede Instanz ein eigenes Topic:
- ble2mqtt/wohnzimmer
- ble2mqtt/schlafzimmer
- ble2mqtt/kueche
Im Attribut devicetopic werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck .* ersetzt wird.
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für rssi und presence. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.
Das "raumübergreifende" Reading presence wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.
define ble2mqttGTag MQTT2_DEVICE FHEM
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF
attr ble2mqttGTag event-on-change-reading .*
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{"$NAME"}->{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,'-100'); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&&(ReadingsVal($NAME,"presence_".$roomTmp,'absent') eq 'present')) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=>$rssiMax,room=>$roomMax,"rssi_$room"=>$EVENT}}
$DEVICETOPIC/lastseen:.* {lastseen=>strftime "%Y-%m-%d %H:%M:%S", localtime($EVENT)}
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,"rssi_".$roomAct,'-100'); my $presenceAct=$EVENT?'present':'absent'; my $room=$EVENT ? $roomAct:''; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}->{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,'absent') eq 'present') {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,"rssi_".$roomTmp,'-100'); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {"presence_$roomAct"=>$presenceAct, room=>$room}}
ble2mqtt/.*/state:.* state
$DEVICETOPIC/battery:.* batteryLevel
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,"lastseen",0)>60) {return "absent";}else{return "present";}}
Das Ergebnis ist unter anderem ein Reading presence mit den Zuständen absent und present. Es kann somit ganz einfach als "presenceDevice" in einem ROOMMATE-Device verwendet werden:
attr rr_Franz rr_presenceDevices ble2mqttGTag