[gelöst]Gleiche Sensoren zusammenführen / priorisieren / aggregieren

Begonnen von Flachzange, 26 Dezember 2024, 12:03:46

Vorheriges Thema - Nächstes Thema

Flachzange

Moin,

folgendes Szenario: Ich habe mehrere Sensoren, die einen Wert für "Helligkeit" (draußen) liefern. Einer (Sensor 2) ist präziser als der andere (Sensor 1). Dafür ist Sensor 2 nicht ganz so zuverlässig (geht alle 1-2 Jahre kaputt und ich muss aufs Dach um ihn zu reparieren). Ich könnte mir auch noch einen Sensor 3 überlegen, der sich einen Wert aus dem Internet holt für meinen Standort.

Aktuell greift meine Automatisierung fix auf Sensor 2 zu. Seit zwei Wochen ist er aber mal wieder kaputt und das mit der Jalousien- und Licht-Seuerung ist entsprechend suboptimal.

Aus Service-Orientieren-Architekturen kenne ich flexible Lösungen, bei denen immer der Sensor genommen wird, der den besten Service zum aktuellen Zeitpunkt liefert. Für mich wäre es OK, wenn ich händisch festlege, welche Sensor aktuell den besten Service liefern. Es muss halt nur switchbar sein. Ich bekomme das aber gerade nicht auf meine FHEM-Werkzeugkiste gemappt, um es wirklich schön generisch zu machen.

Gedanklich / testweise bin ich jetzt mal folgende Ideen durch:

1) Dummy für Ziel-Sensor-Wert + Notifies / DOIFs für Logik
=> Funktioniert immer ist aber sehr hemdsärmelig und nicht wahnsinnig schlank

2) Device-"Weiche": Dummy sagt, von welchem Wert der Helligskeit-Wert genommen werden soll.
=> Unflexibel und eher komplizierter umzusetzen

3) Structure, die auf die Helligskeits-Readings der Devices geht und Attribut event-aggregator, um sich hier immer den max-Wert zu ziehen
=> Kein Platz für wirkliche Logik. event-aggregator funkioniert bei mir in der Kombi nicht, weil state von structure bereits aggeregiert ist. Im Prinzip ist die Structure mit client_state_priority schon sehr nah dran, aber das bezieht sich auf die konkreten, diskreten Werte. Ich kann nicht sagen, Device A hat eine höhere Priorität als Device B.


Jetzt ist das aber doch eigentlich ein Standard-Problem, was der eine oder andere von euch schon bestimmt gelöst hat.

Habt ihr vielleicht den einen odere anderen Denkanstoß für mich?

Besten Dank!

Gruß
Chris

juergen012

Hallo,
nur 2 Helligkeitssenoren..
ich ermittle den Mittelwert.

defmod di_average_Lichtsensor DOIF ##
attr di_average_Lichtsensor DbLogExclude .*
attr di_average_Lichtsensor alias Lichtsensoren Mittelwert
attr di_average_Lichtsensor room DOIF
attr di_average_Lichtsensor state {([HM_Lichtsensor_vorne:CURRENT_ILLUMINATION]+[HM_Lichtsensor_hinten:CURRENT_ILLUMINATION])/2}
attr di_average_Lichtsensor userReadings brightness { ReadingsVal("di_average_Lichtsensor","state",0) }
attr di_average_Lichtsensor verbose 2
Fhem unter Proxmox

rabehd

Ich mache was in der Art für den Luftdruck. Der Mittelwert wird nur für "aktuelle" Werte berechnet.
defmod Luftdruck readingsGroup deCONZ_HUESensor.*:pressure\
MQTT2_SH_Aussenwetter.*:BME280_Pressure\
MQTT2_SH_Innenwetter_WZ.*:BME280_Pressure\
Luftdruck:$avg:r2
attr Luftdruck alwaysTrigger 2
attr Luftdruck mapping %ALIAS
attr Luftdruck valueFormat {ReadingsAge($DEVICE,'pressure',1000)/60 < 60 ? return sprintf("%i hPa", $VALUE) : return undef;;}
Auch funktionierende Lösungen kann man hinterfragen.

Flachzange

Danke für die Impulse. Die Durchschnitt-Berechnung ist ja nochmal ein etwas anderes Problem. In meinem Fall möcht ich ja festlegen, von welchem Sensor die Daten kommen sollen, aber eben veränderbar.

Mit der DOIF-Berechnung im State sollte ich auch über die #max-Aggegration zumindest mein aktues Problem lösen können, auch wenn es noch nicht generisch ist.

@rabehd: Kann ich auf die Werte einer readingsGroup auch zugreifen? Ich kenne sie nur als Liste/Anzeige.

rabehd

Zitat von: Flachzange am 26 Dezember 2024, 18:44:33@rabehd: Kann ich auf die Werte einer readingsGroup auch zugreifen? Ich kenne sie nur als Liste/Anzeige.
Ja, ich verwende den Durchschnitt als Userreading in einem anderen Device.
{ReadingsVal("Luftdruck","avg","1000")}Vermutlich kann man auch auf andere sortiere Einträge zu greifen, aber da sind Andere besser auskunftsfähig.

Auch funktionierende Lösungen kann man hinterfragen.

eisman

#5
hi,

z.B:
mit defmod Watcher readingsWatcher global prüfen ob daten kommen,

if Device1 activity = alive, nimm die daten
elsif Device2 activity = alive, nimm die daten

oder mit doif, nur mal als Beispiel.

ich hatte Watcher für die FHT80b laufen und hatte gute ergebnisse.

gruss

defmod Watcher readingsWatcher global
attr Watcher DbLogExclude .*
attr Watcher alias Watcher
attr Watcher devStateStyle style="text-align:right;;;;"
attr Watcher interval 60
attr Watcher readingActivity activity:dead:alive
attr Watcher room Wohnung
attr Watcher stateFormat devices/alive/dead

im device Attr:
 
readingsWatcher 300,,measured-temp

im device Readings:

activity alive (dead)
********
und dann auswerten
1x FHEM Debian, Homematic,ZigBee,FS20 / 1X Raspberry, ConBee / 5x ESP
1x FHEM Debian, Homematic,ZigBee         / 1X Raspberry, ConBee / 5x ESP
1x FHEM Debian,MQTT                               / 1X Raspberry, i2c,onewire,gpio
1x auf Windows 2012 Hyper-V-S

Flachzange

#6
Zitatz.B:
mit defmod Watcher readingsWatcher global prüfen ob daten kommen,
Daten kommen ja, nur falsche, deswegen muss ich noch händisch etwas an den Sensor anhängen, um ihm zu sagen, dass er gerade nicht genutzt werden soll. In diesem Fall soll dann der nächste beste genommen werden.

Danke aber erstmal für die vielen Ideen.

Ich glaube jetzt eine recht nette Variante via DOIF gefunden zu haben, die man natürlich beliebig erweitern kann, um die "Güte" eines Sensors zu bewerten und dann hier abzufragen. Einzig die max-Aggregation ist hier jetzt noch sehr spezifisch, weil mein kaputter Sensor immer 0 sendet.

defmod DOIF_Weather_Brightness DOIF ##
attr DOIF_Weather_Brightness room Wetter
attr DOIF_Weather_Brightness state [#max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1"]

Edit: DOIF nochmal leicht angepasst

@Damian, falls Du zufällig mitliest: Gemäß commandref kann ich am Ende einen default-Wert mitgeben, wenn ich aber beispielsweise

attr DOIF_Weather_Brightness state [#max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1",-1]
definiere, ist das Ergebnis immer -1



Ralli

#8
Ich aggregiere mittels DOIF und lege dabei fest, dass ein Wert nur dann einbezogen wird, wenn er nicht älter als 1800 Sekunden ist. Damit kompensiere ich mögliche Ausfälle eines einzelnen Sensors und ggf. durch diesen verfälschte Werte.

Ich habe zwei Homematic-Lichtsensoren, einen Homematic Temperatur-Sensor sowie eine Bresser 7in1-Wetterstation.

defmod GEN_Aussensensor DOIF ##
attr GEN_Aussensensor event-min-interval .*:20
attr GEN_Aussensensor event-on-change-reading .*
attr GEN_Aussensensor event-on-update-reading LUMINOSITY,TEMPERATURE,HUMIDITY
attr GEN_Aussensensor event_Readings LUMINOSITY:[#max:d1:"CEN_Lichtsensor_?|MQTT2_Bresser7in1:1.CURRENT_ILLUMINATION":1.CURRENT_ILLUMINATION:ReadingsAge($name,"1.CURRENT_ILLUMINATION",0) < 1800],\
TEMPERATURE:[#average:d1:"CEN_Temperatursensor_?|MQTT2_Bresser7in1:1.ACTUAL_TEMPERATURE":1.ACTUAL_TEMPERATURE:ReadingsAge($name,"1.ACTUAL_TEMPERATURE",0) < 1800],\
HUMIDITY:[#average:d1:"CEN_Temperatursensor_?|MQTT2_Bresser7in1:1.HUMIDITY":1.HUMIDITY:ReadingsAge($name,"1.HUMIDITY",0) < 1800],\
WIND:[#max:d1:"MQTT2_Bresser7in1:windSpeed_kmh":windSpeed_kmh:ReadingsAge($name,"windSpeed_kmh",0) < 1800],\
UV:[#max:d1:"MQTT2_Bresser7in1:uv":uv:ReadingsAge($name,"uv",0) < 1800],\
DEV_LUMINOSITY:[@"CEN_Lichtsensor_?|MQTT2_Bresser7in1:1.CURRENT_ILLUMINATION":1.CURRENT_ILLUMINATION:ReadingsAge($name,"1.CURRENT_ILLUMINATION",0) < 1800],\
DEV_TEMPERATURE:[@"CEN_Temperatursensor_?|MQTT2_Bresser7in1:1.ACTUAL_TEMPERATURE":1.ACTUAL_TEMPERATURE:ReadingsAge($name,"1.ACTUAL_TEMPERATURE",0) < 1800],\
DEV_HUMIDITY:[@"CEN_Temperatursensor_?|MQTT2_Bresser7in1:1.HUMIDITY":1.HUMIDITY:ReadingsAge($name,"1.HUMIDITY",0) < 1800]\

attr GEN_Aussensensor stateFormat {no warnings;;\
 my $ap = ReadingsNum($name,"HUMIDITY",0);;\
 my $tp = ReadingsNum($name,"TEMPERATURE",0);;\
 my $lm = ReadingsNum($name,"LUMINOSITY",0);;\
 my $uv = ReadingsNum($name,"UV",0);;\
 my $ws = ReadingsNum($name,"WIND",0);;\
 my $wd = "";;\
 $wd .= " (".ReadingsVal("MQTT2_Bresser7in1","windDirectionText","").")" if ($ws > 0);;\
 $wd =~ s/E/O/g;;\
 sprintf("TMP: %.1f LUX: %.1f UV: %.1f HUM: %.1f WND: %.1f",$tp,$lm,$uv,$ap,$ws).$wd}
Gruß,
Ralli

Proxmox 8.3 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.3 dev, virtualisierte RaspberryMatic (3.79.6.20250220) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.1.5) und HMW-GW, FRITZBOX 7490 (07.59), FBDECT, Siri und Alexa

Flachzange

Zitat von: Martin Fischer am 29 Dezember 2024, 01:29:06https://fhem.de/commandref_DE.html#structure
https://wiki.fhem.de/wiki/Structure

So so, hast Du auch mehr als nur den Titel meines Beitrags gelesen? :)

Ich hatte ja schon erwähnt, dass ich mir Structure angeschaut habe, aber ich seh nicht, wie sie mein Problem lösen kann.

Aber ich mache hier mal zu. Der Einzeiler mit DOIF funktioniert für mich und ist auch generalisierbar

Danke für die vielen Vorschläge.

Damian

Zitat von: Flachzange am 26 Dezember 2024, 23:18:17@Damian, falls Du zufällig mitliest: Gemäß commandref kann ich am Ende einen default-Wert mitgeben, wenn ich aber beispielsweise

attr DOIF_Weather_Brightness state [#max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1",-1]
definiere, ist das Ergebnis immer -1

Ich habe es gefixt. Morgen per Update verfügbar.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Flachzange

Danke. Habe gerade aktualisiert und getestet, aber ändert leider nichts.

Damian

Zitat von: Flachzange am 05 Januar 2025, 15:15:35Danke. Habe gerade aktualisiert und getestet, aber ändert leider nichts.

Dann poste noch mal die aktuelle Konfiguration, denn nach meinen Tests war der eindeutig identifizierbarer Fehler behoben.

Version 98_DOIF.pm sollte Folgendes liefern:

98_DOIF.pm 29460 2024-12-29 20:25:48Z Damian
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Flachzange

Zitat von: Damian am 05 Januar 2025, 15:19:5498_DOIF.pm 29460 2024-12-29 20:25:48Z Damian
passt.

Also Ausdruck ist nach wie vor:

attr DOIF_Weather_Brightness state [#max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1",-1]
Beide Sensoren liefern aktuell Werte > 0

disable ist bei beiden 0 gesetzt

Damian

Zitat von: Flachzange am 05 Januar 2025, 15:53:29
Zitat von: Damian am 05 Januar 2025, 15:19:5498_DOIF.pm 29460 2024-12-29 20:25:48Z Damian
passt.

Also Ausdruck ist nach wie vor:

attr DOIF_Weather_Brightness state [#max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1",-1]
Beide Sensoren liefern aktuell Werte > 0

disable ist bei beiden 0 gesetzt

Was liefert denn? (@ statt #)

[@max:"^(TF_AHDSB|Weatherman):brightness":brightness:AttrVal($name,"disable","") ne "1",-1]


Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF