ble2mqtt - Bluetooth Anwesenheitserkennung

Begonnen von drhirn, 07 April 2022, 13:45:09

Vorheriges Thema - Nächstes Thema

gestein

Hallo Beta-User,

dieser Eventstapel erleichtert mir auch einiges. Cool.

Eine Frage bitte noch:
In Deiner Funktion "identifyMyBestGW" hast Du diesen wirklich coolen Code:
my $hash = $defs{$name};
my @rssis = grep { $_ =~ /.*_rssi/ } sort keys %{ $hash->{READINGS} };


Kann man das "grep" so erweitern, dass es alle Readings mit "_rssi" am Ende liefert, aber das Reading auslässt, dessen Raumname in der Variablen $room steht?
Also in der Art:
   Vorzimmer_rssi
   room
   state
   Wohnzimmer_rssi
   Garage_rssi

Wenn $room="Vorzimmer" ist, dann sollte @rssis enthalten "Wohnzimmer_rssi, Garage_rssi",.
Das würde meinen Code sehr vereinfachen.

Danke schon mal.
lg, Gerhard

Beta-User

Geht vermutlich schon, wenn man ein (?!$room) da reinknödelt.

Einfacher ist es vermutlich, ein "next if $_ eq $room;" an den Beginn der Schleife zu stellen.

OT: Der Code ist auch schon wieder etwas angejahrt, würde ich heute auch anders schreiben (für was wird da sortiert?):

my @rssis = grep { $_ =~ m{.*_rssi\z}x } keys %{ $hash->{READINGS} };
Und das andere dementsprechend:
$DEVICETOPIC/present:.* {my $room=(split m{[/]}x, $TOPIC)[1]; my $ret = $EVENT ? 'present' : 'absent'; { "presence_$room"=>$ret, state=>$ret } }
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

gestein

Cool. Danke für die vielen Hinweise.
Das hier sollte funktionieren - kurz und prägnant  ;)

$DEVICETOPIC/present:.* {my $room=(split /\//,$TOPIC)[1]; my $presenceRoom=$EVENT? "present":"absent"; my $presence=$presenceRoom; my @readings = grep { $_ =~ m{^presence_(?!$room).*}x } keys %{$defs{"$NAME"}->{READINGS}}; foreach (@readings) {if(ReadingsVal("$NAME","$_","absent") eq "present") {$presence="present"; last}}; {"presence_$room"=>"$presenceRoom","presence"=>"$presence","state"=>"$presence"}}

Mal schauen, wie man damit auch den Raum und das rssi schön lösen kann.
Rein aus Interesse.

lg, Gerhard

Beta-User

Meine "Hinweise" zu
- Interpolation (http://perlmeme.org/howtos/using_perl/interpolation.html, wann wo wie benötigt, und wo eben auch nicht...),
- "foreach" und
- genauerer Anweisung an den Perl-Interpreter, wie die regex zu verstehen ist (auch im split),
scheinen demnach nicht so interessant gewesen zu sein ::) ...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

gestein

Hallo Beta-User,

ich weiß jetzt nicht genau, was Du meinst.
Die allermeisten Ideen und vor allem den Code habe ich doch von Dir übernommen.

lg, Gerhard

Beta-User

Dein Ergebnis:
$DEVICETOPIC/present:.* {my $room=(split /\//,$TOPIC)[1]; my $presenceRoom=$EVENT? "present":"absent"; my $presence=$presenceRoom; my @readings = grep { $_ =~ m{^presence_(?!$room).*}x } keys %{$defs{"$NAME"}->{READINGS}}; foreach (@readings) {if(ReadingsVal("$NAME","$_","absent") eq "present") {$presence="present"; last}}; {"presence_$room"=>"$presenceRoom","presence"=>"$presence","state"=>"$presence"}}
Mein Vorschlag für eine sauberere Schreibweise:
$DEVICETOPIC/present:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $presenceRoom=$EVENT ? 'present':'absent'; my $presence=$presenceRoom; my @readings = grep { $_ =~ m{\Apresence_(?!$room).*}x } keys %{$defs{$NAME}->{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,'absent') eq 'present') {$presence='present'; last}}; {"presence_$room"=>$presenceRoom, presence=>$presence,state=>$presence}}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

gestein

Das mit dem "m{[/]}x" in der regex für das split hatte ich doch glatt übersehen.
Danke.
Beim grep habe ich es dafür ja schon ;)

Und statt dem "foreach" ein "for" zu nehmen, ist auch kein Thema.
Auch die Hochkomma werde ich mir mal zu Gemüte führen.

Danke für die Hinweise.

Im Code selbst haben sich noch ein paar Änderungen ergeben.
Nun läuft es mal und ich werde ausführlich testen.

lg, Gerhard

gestein

Hallo,

könnte mir bitte jemand dabei helfen das "ble2mqttd" beim Start des raspi automatisch zu starten?
Wie macht man das?

Danke, lg, Gerhard

Stelaku

ich mach das über die rc.local datei
Zitat
/etc/rc.local

Gruss

Stephan

MadMax-FHEM

Kommt auf das System an.

Bis Stretch (wobei ab dort beides geht) war initd, also ein Startscript in /etc/initd

Ab Stretch dann systemd, also eine Unit-Datei in /etc/systemd/system

In jedem der genannten Ordner sind Beispiele vorhanden, ansonsten Internet oder eben mitteilen, was die Basis ist.
Siehe "Einleitung"...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

gestein

Hallo,

Danke erstmal für die Tipps.
Ich starte ble2mqttd nun über die Datei "/etc/rc.local".

Mittlerweile klappt das mit ble2mqtt ganz gut.
Die Multiraum-Lösung ist etwas komplizierter.

Hier meine Lösung dafür:
defmod mqtt_Gtag_orange MQTT2_DEVICE
attr mqtt_Gtag_orange IODev MQTT2_FHEM_Server2
attr mqtt_Gtag_orange comment https://forum.fhem.de/index.php/topic,127173.msg1226199.html#msg1226199
attr mqtt_Gtag_orange devicetopic ble2mqttd/.*/7C_2F_80_99_D8_A3
attr mqtt_Gtag_orange event-on-change-reading .*
attr mqtt_Gtag_orange readingList $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 $presenceTotal=$presenceAct;; 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;;$presenceTotal='present';; $rssi=$rssiTmp}}};; {"presence_$roomAct"=>$presenceAct, room=>$room, presence=>$presenceTotal, state=>$presenceTotal}}\
$DEVICETOPIC/LWT:.* LWT
attr mqtt_Gtag_orange room MQTT2_DEVICE


Funktioniert bei mir mit 2 raspberry zero und dem eingebauten Bluetooth-Chip ohne Probleme.
Jetzt wäre es schön auch noch das LWT und den Batterie-Status zu bekommen  ;)
Weihnachten kommt ja bald ...

lg, Gerhard

drhirn

Kannst du mir bitte in Worten erklären, was in der Zeile passiert? Ich bin so scheiße in Perl ;)
attr mqtt_Gtag_orange readingList $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}}\

Übrigens experimentiere ich gerade mit OpenMQTTGateway (ESP). Bzw. Theengs Gateway (Linux, Windows). Das wären schon fertige Lösungen, mit denen wir das Rad nicht neu erfinden müssten.

gestein

Hm, in Worten? Das ist mal eine Herausforderung  ;)

Im Prinzip möchte ich bei mehreren Räumen die Signalstärke pro Raum als Reading im Device haben "z.B. rssi_Vorzimmer -76; rssi_Wohnzimmer -71" und den Raum mit dem besten Empfang im reading "room" sowie die entsprechende Signalstärke im Reading "rssi".
Also z.B.:
room             Wohnzimmer
rssi               -71
rssi_Vorzimmer     -76
rssi_Wohnzimmer    -71


Die einzelnen raspberry schicken die MQTT-Meldungen (sagt man das so?) aber zu unterschiedlichen Zeitpunkten.
Daher muss ich mir zuerst mal den aktuellen Raum aus dem Topic holen (my $room=(split m{[/]}x,$TOPIC)[1];).
Die aktuelle Signalstärke steht im Event (my $rssiMax=$EVENT;).

Dann suche ich alle Readings im Device, die mit "rssi_" beginnen - außer natürlich dem aktuellen. Denn dafür sind ja wahrscheinlich geänderte Werte geschickt worden.
Das feine Stück Code dafür habe ich selbst nur von Beta-User bekommen (my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{"$NAME"}->{READINGS}};).
Warum und wie das funktioniert, verstehe ich leider auch noch nicht.

Dann muss ich nur noch alle Einträge im Array durchlaufen und die rssi-Werte vergleichen und mir gegebenfalls merken.

Zu guter Letzt werden die gefundenen Werte in einem Block an das Device übergeben ({rssi=>$rssiMax,room=>$roomMax,"rssi_$room"=>$EVENT}}).

Hilft diese Erklärung etwas?
lg, Gerhard

drhirn

Ja, danke Gerhard! Dann habe ich das richtig interpretiert.
Bei mir wird über einen "bad reading name" gemeckert. Das muss ich mir mal in Ruhe ansehen.

PatrickR

#59
Hi!

Zitat von: gestein am 03 November 2022, 18:21:56
Jetzt wäre es schön auch noch das LWT und den Batterie-Status zu bekommen  ;)
Weihnachten kommt ja bald ...

Den roten Mantel hatte ich schon an und dachte in meinem jugendlichen Leichtsinn, ich baue schnell das LWT ein. Gesagt getan. Funktioniert nur nicht, weil Net::MQTT::Simple Grütze ist... ich Grütze bin...

/Edit:
Version 0.06 mit LWT (topic: 'state') im Anhang.

/Edit 2:
Anhang entfernt.

Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook