Abfrage mit Wildcard, Bus ist überfordert

Begonnen von GammaTwin, 03 August 2017, 21:24:01

Vorheriges Thema - Nächstes Thema

GammaTwin

Grüße,

ich bin sehr zufrieden mit FHEM. Manchmal gelingt es mir allerdings in FHEM andere Zustände zu sehen als im KNX-System. Ich bin zwar immer selber Schuld, da immer der Server offline ist und so natürlich die Änderung nicht wahrgenommen wurde.
Mir ist jetzt eine elegante Lösung eingefallen. Leider gibt es da ein Problem...

Man könnte jede Gruppenadresse einzeln abfragen, z.B.:
get KNX_0301050

Da alle Gruppenadressen mit  "KNX_" anfangen, kann man auch folgende Wildcard-Konstruktion benutzen
get KNX_.*
FHEM wirft dann alle Requests mit einmal auf den Bus.

Dies konnte ich mit einem kleinen Bereich get KNX_0101.* erfolgreich testen.

Bei get KNX_.* wird allerdings die Buslast wird zu groß. In der ETS wird dann "Timeout" angezeigt und kein Telegramm beantwortet.

Zur Frage:
Was müsste man tun, um die nur z.B. 10 Telegramme pro Sekunde auf den Bus zu werfen?


EIB-Fan

Hallo GammaTwin,

ohne dir eine Lösung präsentieren zu können, möchte ich dir meinen Gedanken zu deiner Problematik weitergeben.

Nach meinem Verständnis kannst du hier in knxd die Cache-Funktion nutzen. Schau mal im Bereich "cache-section".

https://github.com/knxd/knxd/wiki/Command-line-parameters

Ich nutze dies selber nicht, kann dir hier also keine weiteren Programmiertipps geben.

Ich kann mit dem Gedanken aber auch völlig falsch liegen ... :o

Gruß Jens


GammaTwin

Hallo Jens,

das Cachen der Werte auf der Ebene KNXD ermöglicht aktuelle Daten, selbst wenn man den FHEM-Server einmal nicht laufen hat. Keine schlechte Idee.
Ich packe das mal in die "Pevensionsecke".  :) Nichts mehr verpassen.

Ich hätte aber gern noch eine reaktive Möglichkeit - einfach mal alle Gruppenadessen abzufragen.  8)

Gruß Marco


GammaTwin

Grüße,

habe etwas gebastelt und bin zu folgendem Schluss gekommen: Eine globale Abfrage verhält sich nicht sonderlich robust.

Vielleicht helfen einige meiner Experimente bei anderen Fragestellungen weiter:

1. Stumpfe globale Abfrage
get KNX_.*
Problem 1: Legt den Bus sofort lahm :)
Problem 2: Fragt nur die erste Gruppenadresse ab
define KNX_0103021 KNX 1/3/21:dpt5.001 1/4/21:dpt5 1/5/21:dpt5.001
Bei dieser Leuchte ist g1 dimmen absolut, g2 dimmen relativ und g3 der aktuelle Dimmwert. Die globale Abfrage fragt 1/3/21 ab. Diese antwortet aber nicht. Antworten würde 1/5/21.
Schon dieser Fakt macht meine Idee schwierig.

2. Lösung über ein Array
define n_Test_Wildcard notify n_Test_Wildcard {\
my @knxi=devspec2array("TYPE=KNX");;\
foreach(@knxi) {\
  fhem("define n_.$_ at +00:05:01 get $_");;\
  }\
}

Ziel war es, für jeden Device ein at zu erzeugen. Dann wollte ich über eine Variable die Zeit pro at erhöhen und so den Bus schonen. Die +00:05:01 war nur dafür da, damit ich sehen konnte, ob das Anlegen funktioniert hat.
Positv 1: die at werden angelegt.
Problem 1: es wurde 403 at angelegt :) FHEM war für ca. 2min30s nicht ansprechbar  :o Das Anlegen der at war so langsam, dass die Zeiten genügend anstiegen, ganz ohne die Defintion einer Variable  8)
Postiv 2: der Bus konnte alle anfragen abarbeiten :)
Problem 2: da wiederum nur die erste Gruppenadresse abgefragt wurde, ist dies wieder nicht sonderlich hilfreich.

3. Eine Mischung aus konkreten Abfragen und Wildcards
Da meine Gruppenadressen einer strikten Logik folgen, kann ich gewisse Gruppen abfragen. z.B. bildet die Beleuchtung eine Hauptgruppe. Die Rückmeldewerte der Dimmwerte befinden sich in der Mittelgruppe 5. Die Leuchten sind dann die Subgruppe. Damit kann ich mit folgenden notify alle Dimmwerte abfragen.
define n_KNX_0105_Status notify manStatus:.*Dimmen \
define n_KNX_0103_0 at +00:00:03 get KNX_0103.0. g3;;\
define n_KNX_0103_1 at +00:00:04 get KNX_0103.1. g3;;\
define n_KNX_0103_2 at +00:00:05 get KNX_0103.2. g3;;\
define n_KNX_0103_3 at +00:00:06 get KNX_0103.3. g3;;\
define n_KNX_0103_4 at +00:00:07 get KNX_0103.4. g3;;\
define n_KNX_0103_5 at +00:00:08 get KNX_0103.5. g3;;\
define n_KNX_0103_6 at +00:00:09 get KNX_0103.6. g3;;\
define n_KNX_0103_7 at +00:00:10 get KNX_0103.7. g3;;\
define n_KNX_0103_8 at +00:00:11 get KNX_0103.8. g3;;\
define n_KNX_0103_9 at +00:00:12 get KNX_0103.9. g3

Ich kreiere damit 10 at, die nacheinander ablaufen. Damit halte ich die Buslast unter Kontrolle. Die Wildcard "." sorgt dafür, dass mit diesen 10 at alle 255 Gruppenadressen abgefragt werden.
Mit 2 solchen notifys kann ich für Leuchten den Schaltzustand und den Dimmwert abfragen. Ein weiteres notify für Jalousien und noch eins die Stellwerte der Heizung. Diese 4 notify kann man dann schön gestaffelt ablaufen lassen.
Positiv: Es funktioniert und alle Systeme (KNX-Bus, FHEM, smartVISU) sind jederzeit ansprechbar :D
Negativ: Dauert ca. 2 Minuten

Mein Fazit:
Global Abfragen führt zu hoher Buslast und nicht alle gewünschten Antworten.
Einzelne Aktualisierungs-notify mit Wildcards funktionieren, wenn die Gruppenadressen einer Logik folgen.

Mir reicht diese Lösung, um auch nach längerem "Server-Aus" die Visu mit aktuellen, vertrauenswürdigen Zuständen zu versorgen.

Falls jemand etwas auffällt, gerne posten.

Marco

JoeALLb

Hallo Marco,

hast Du versucht, statt lauter ATs ein DOIF mit sämtlichen Abfragen als DOELSEIF anzulegen?
Ich hatte das im Frühjahr mal das benutzt da es deutlich performanter war und der Überblick blieb mir auch erhalten.
Ich konnte das DOIF auch als Dauerdevice "behalten", habe es lediglich disabled, wenn ich es gerade nicht benötige.

.... Vielleicht hilft dieser Gedanke?!?

sG
Joe

FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

eburkon

Servus Miteinander,

ich habe auch keine direkte Lösung aber evtl. eine Anregung.

Vor einiger Zeit habe ich mit MrHouse gespielt. (Lebt das Projekt noch?)

Dort war es so, dass die  EIB/KNX Geräte nach dem Neustart alle abgefragt wurden allerdings zeitversetzt.

Finde ich einerseits etwas Semi, weil auch das eine durchaus ordentliche Buslast erzeugt wird und es in vielen Fällen
nicht nötig ist.

Ich fände es nett wenn es bei KNX Devices ein Attribut gäbe mit dem man ein derartiges Verhalten steuern könnte.

Oder evtl könnte auch folgendes funktionieren:

Alle betroffenen Geräte in eine Gruppe stecken und mit etwas Code die Mitglieder der Gruppe nach dem Neustart abfragen.

Gruss
    Ekkehard
FHEM auf Rpi48G, KNX via knxd und IP Interface, Hue, FS20, und ein paare externe Sachen via MQTT

CoolTux

Erweitere Dein foreach so das alles Devices zusammen getragen werden.
Danach lässt Du den get Befehl zusammenstellen der alle Devices nacheinander schreibt aber zwischen jedem 5 Device ein FHEM sleep von 10s ein baut.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

eburkon

Blockieren die sleeps nicht FHEM als solches, wenn die Schleife mal 100 Durchläufe hat?
FHEM auf Rpi48G, KNX via knxd und IP Interface, Hue, FS20, und ein paare externe Sachen via MQTT

CoolTux

Deswegen ein FHEM-sleep in einem FHEM Befehl

fhem("get device1,device2,device3;sleep 5;get device4,device5...");


So sollte dann der fertige fhem Befehl aussehen. Halt alle 5 Devices ein sleep. Die Schleife baut den fhem Befehl nur zusammen, ausserhalb der Schleife wird er dann ausgeführt.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

GammaTwin

#9
Grüße,

nachdem ich jetzt 1,5 Jahre mein "Problem" mit der Aktualisierung aller KNX-Zustände nicht zufriedenstellend gelöst habe, hatte ich einen Geistesblitz. Diesen möchte ich Euch gern zeigen.

Ziel ist es, alle KNX-Zustände abzufragen, ohne den Bus zu überlasten. Gelöst habe ich es über einen Dummy und ein Notify. Der Dummy ist der Schalter und das notify führt aus.
Im Dummy habe ich auch den Wert für den Fortschrittsbalken für die smartVISU intergiert.

Der Schalter
define KNX_Status_Aktualisierung dummy
attr KNX_Status_Aktualisierung devStateIcon on:on: off:off:on
attr KNX_Status_Aktualisierung setList state:on,off
attr KNX_Status_Aktualisierung userReadings AnzAbfrageMax {if (ReadingsNum($NAME, 'AnzAbfrageIst', '') > ReadingsNum($NAME, 'AnzAbfrageMax', '')) {ReadingsNum($NAME, 'AnzAbfrageIst', '')} else {ReadingsNum($NAME, 'AnzAbfrageMax', '')} },ProzentAbfrage { int(100 * ReadingsNum($NAME, 'AnzAbfrageIst', '') / ReadingsNum($NAME, 'AnzAbfrageMax', ''))}


Die Ausführung
define n_KNX_Status_Aktualisierung notify KNX_Status_Aktualisierung:.*on {
my @aKNXDevice=devspec2array("TYPE=KNX");
my $iSleep=0;
my $TelegrammeProSek=5;
foreach my $KNXDevice (@aKNXDevice) {
  my $KNXDev=InternalVal($KNXDevice,'DEF','NIX');
  my @aKNXAdress=split(/ /,$KNXDev);
  my $iDev=0;
  foreach my $KNXAdress (@aKNXAdress) {
   $iDev++;
   if (substr($KNXAdress,length($KNXAdress)-4,4) ne ":set" and substr($KNXAdress,length($KNXAdress)-11,11) ne ":listenonly") {
    fhem("sleep ".int($iSleep / $TelegrammeProSek)."; get $KNXDevice g$iDev");
    $iSleep++;
    fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageIst $iSleep");
    };
   };
  };
  fhem("sleep ".int($iSleep / $TelegrammeProSek)."; set KNX_Status_Aktualisierung off");
  fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageMax 0");
  fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageIst 0");
}



Die Funktionsweise:
1. Mit Start des notify, wird ein Array alle KNX-Devices angelegt.
my @aKNXDevice=devspec2array("TYPE=KNX")

2. Mittels Schleife (foreach) wird jedes KNX-Device folgendermaßen behandelt. Jedes KNX-Device kann mehrere Gruppenadressen in der DEV enthalten. Diese sind durch Leerzeichen getrennt. Es wird ein Array aller Gruppenadressen angelegt
my $KNXDev=InternalVal($KNXDevice,'DEF','NIX');
my @aKNXAdress=split(/ /,$KNXDev);


3. Mittels Schleife (foreach) wird jede Gruppenadresse geprüft, ob diese ausgelesen werden kann, bzw. "set" und "listenonly" werden nicht antworten und deshalb nicht abgefragt.
if (substr($KNXAdress,length($KNXAdress)-4,4) ne ":set" and substr($KNXAdress,length($KNXAdress)-11,11) ne ":listenonly") {
Hier ist meine Lösung anfällig, da sie nur für meine Art der DEV funktioniert. Ich gebe nur  <group>:<DPT>:[set|get|listenonly] an (allgemein: define <name> KNX <group>:<DPT>:[gadName]:[set|get|listenonly]:[nosuffix] [<group>:<DPT> ..] [IODev])

4. über das FHEM-sleep und die Variablen wird die Anzahl der Anfragen pro Sekunde begrenzt.
fhem("sleep ".int($iSleep / $TelegrammeProSek)."; get $KNXDevice g$iDev");
Auch hier ist diese Lösung anfällig, da der Name des Device "g1, g2, ..." abgefragt wird. Sollte jemand :[gadName]: verwenden, müsste nachgebessert werden.

5. Als Nebeneffekt bekomme ich die Anzahl alle mögliche Abfragen geliefert.
fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageIst $iSleep");
Diesen Wert nutzt dann das userReadings im Dummy für den "Ladebalken" in der Visu.

6. Zum Schluss werden die Zähler für den Fortschrittsbalken korrigiert.
fhem("sleep ".int($iSleep / $TelegrammeProSek)."; set KNX_Status_Aktualisierung off");
fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageMax 0");
fhem("sleep ".int($iSleep / $TelegrammeProSek)."; setreading KNX_Status_Aktualisierung AnzAbfrageIst 0");

Durch die Reihenfolge steht am Ende immer die aktuelle Anzahl der Abfragen im AnzAbfrageMax.

Eine Frage habe ich noch:
Wie kann ich aus dieser Zeile
if (substr($KNXAdress,length($KNXAdress)-4,4) ne ":set" and substr($KNXAdress,length($KNXAdress)-11,11) ne ":listenonly") {
als Regex abfragen?

Bin gespannt, wir ihr die Lösung findet.

Gruß,
Marco