Neue Version von HTTPMOD mit neuen Features zum Testen

Begonnen von StefanStrobel, 05 Dezember 2015, 08:31:32

Vorheriges Thema - Nächstes Thema

ch.eick

Zitat von: StefanStrobel am 11 Oktober 2022, 17:01:14
Hallo Christian,

der spannende Teil müsste im Log ein paar Zeilen höher stehen.
Zudem wäre es fürs Verständnis wichtig Die volle Konfiguration des Set und der relevanten Readings zu kennen.

Gruß
   Stefan
Hallo Stefan und danke für die Rückmeldung

ich meine es jetzt gefunden zu haben.

Weiter oben im Log stand leider nichts, da die Ersetzung gar nicht durchlaufen wurde :-)

Durch die Verwendung von "set[0-9]*NoArg" habe ich mir wohl die Evaluierung mit "set[0-9]+IExpr" selber ausgehebelt.
Ursprünglich hatte ich vor mit "set[0-9]*hint 0,1,2," im pulldown Menü auch eine leere Eingabe zuzulassen.
Dies habe ich jetzt auf die Auswahl einer Text Strings geändert und das "set[0-9]*NoArg" daraufhin gelöscht.
Momentan sieht es so aus, dass ich jetzt weiter komme.

Soll ich meinen letzten Post wieder löschen, damit niemand verwirrt wird?

VG   Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

StefanStrobel

Hallo Christian,

vielleicht hilft es ja jemandem mit einem ähnlichen Problem. Die Ursache / Lösung ist ja jetzt bekannt. Ich schau auch mal ob ich die Kombination IExpr und NoArg im Modul sinnvoll ermöglichen kann.


Gruß
    Stefan

ch.eick

#1187
Zitat von: StefanStrobel am 11 Oktober 2022, 17:45:45
vielleicht hilft es ja jemandem mit einem ähnlichen Problem. Die Ursache / Lösung ist ja jetzt bekannt. Ich schau auch mal ob ich die Kombination IExpr und NoArg im Modul sinnvoll ermöglichen kann.
Hallo Stefan,
aber nur wenn es Sinn macht, man kann es ja auch wie folgt mit einem String machen

attr WR_1_API set2404Name 24__3_Battery_TimeControl_Mi
attr WR_1_API set2404URL http://%IP-WR%/api/v1/settings
attr WR_1_API set2404Header01 authorization: Session %auth_sessionId%
attr WR_1_API set2404Header02 Content-type:application/json, Accept:application/json, Connection:keep-alive
attr WR_1_API set2404Method PUT

attr WR_1_API set2404Hint 0,1,2,Battery_TimeControl_3_Mi
attr WR_1_API set2404TextArg 1

attr WR_1_API set2404IExpr my $x = ReadingsVal($name,$val,"null");; $x=~s/\s//gs;; ($val =~ /^-?\d+$/)? $val x96 : ($x =~ /^-?\d+$/)? $x : 0 x96
attr WR_1_API set2404Data [{"moduleid":"devices:local","settings":[{"id":"Battery:TimeControl:ConfWed","value":"$val"}]}]

attr WR_1_API set2404FollowGet 24_Battery_TimeControl


Bei dieser Konfiguration geht es darum einen Formatierten String in den readings zu haben, der wie folgt aussieht

Battery_TimeControl_3_Mi 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

Jede Stelle kann [0-2] annehmen und jeder 4er Block entspricht einer Stunde, somit gibt es 24 Blöcke. Die Trennung in Blöcke habe ich wegen der Lesbarkeit eingeführt.
Zum Senden muss die dann jedoch wieder ohne Blanks sein.

Beim set hat man nun die Möglichkeit
-  [0-2] auswählen, was dann wiederum einheitlich 96 mal geschrieben wird.
-  Den Text zu wählen, was dann versucht das reading zu lesen
   ist das reading nicht vorhanden wird wiederum 96 mal 0 geschrieben, was einem abschalten innerhalb des Gerätes gleich kommt.
-  Das jeweilige reading kann jedoch auch aus einem anderen Device in dieses geschrieben werden, was eine Formatierung des gesamten Strings mit [0-2] durch eine Funktion ermöglicht.

Angewendet habe ich es dann hier.

VG
   Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Aurel_B

Ich durfte mich soeben auch mit IExpr beschäftigen, es klappt alles wie erwartet:


attr foo set1Data [{"name":"bar", "value":"$val"}]
attr foo set1Name Foobar
attr foo set1IExpr $val*100


sendet - falls "set Foobar 2" gesetzt wird - korrekt [{"name":"bar", "value":"200"}]. Vielleicht könnte man die Doku noch ergänzen? Ein Vorschlag:


set[0-9]+IExpr
Perl Expression to compute the raw value to be sent to the device from the input value passed to the set. E.g. "$val*100" will multiply $val by 100 after a set command, the thusly modified $val will then be used in subsequent processing, e.g. "(get|set)[0-9]*Data" will use the modified $val

Aurel_B

Ah und noch eine Frage: ich habe eine M-Tec Wärmepumpe die leider nur sehr begrenzte Modbusregister anbietet. Also frage ich alles via HTTPMOD ab, das klappt auch wunderbar. Ich muss dazu allerdings 2 HTTPMOD Instanzen nehmen, eine für das Auslesen und eine für das Setzen. Grundsätzlich läuft die Kommunikation wie folgt:

Ein HTTP Post mit

[
  {
    "name": "APPL.CtrlAppl.sParam.heatCircuit[0].values.setValue"
  },
  {
    "name": "APPL.CtrlAppl.sParam.outdoorTemp.values.actValue"
  }
]


liefert dann


[
  {
    "name": "APPL.CtrlAppl.sParam.heatCircuit[0].values.setValue",
    "value": "20.5"
  },
  {
    "name": "APPL.CtrlAppl.sParam.outdoorTemp.values.actValue",
    "value": "3.993516"
  }
]


zurück.

Folgende Fragen habe ich

  • Da die Antwort IMHO nicht vom JSON Parser von HTTPMOD erfasst werden kann (weil quasi Variablenname und Variablenwert in 2 separaten "Arrayeinträgen" zurückgeschickt wird) habe ich ein Regex verwendet, z.B. reading01Regex outdoorTemp\.values\.actValue","value":"([\d\.]+)". Funktioniert wunderbar. Ein probehalber verwendetes extractAllJSON 2 brachte keine vernünftigen Readings hervor. Habe ich da etwas übersehen oder lässt sich die Antwort tatsächlich nicht mit dem JSON-Extraktor von HTTPMOD parsen?
  • Ich frage alles 20s ca. 40 Werte ab und verwende dafür ein HTTPMOD Device mit einem RequestData wo alle Anfragen drin sind. Viele dieser Werte müsste ich nicht so oft abfragen. Kann ich das irgendwie eleganter lösen? Also dass - wie beim Modbus Modul wo ja jedes Register einzeln definiert wird und über das Combine Attribut dann mehrere Register zusammen abgefragt werden - ich alles in einzelne "get" Commands herunterbreche und diese dann kombiniert - je nach PollDelay - versendet werden?
  • Kann man get und set "zusammenlegen", also dass ein "Temperatur_Soll" nur 1x existiert als Reading und sowohl gesetzt als auch gelesen werden kann?

Also quasi zusammengefasst: wie kann ich das Verhalten von HTTPMOD dem des Modbus Modules anpassen? 1 Register mit 1 Name welches gelesen und beschrieben werden kann und wo mehrere "Register" gebündelt mitgeschickt werden (damit nicht 40 einzelne Anfragen innerhalb kürzester Zeit auf die Wärmepumpensteuerung hereinprasseln)?

Danke vielmals!

Hier noch für die Vollständigkeit die beiden "Get/Set" Devices:


defmod WP_Get HTTPMOD http://wp/var/readWriteVars?languageCode=de 20
attr WP_Get enableControlSet 1
attr WP_Get enableCookies 1
attr WP_Get enforceGoodReadingNames 1
attr WP_Get handleRedirects 1
attr WP_Get reading01Name Umwaelzpumpenleistung_WPLK_Prozent

attr WP_Get reading01Regex heatCircuit\[0\]\.param\.normalSetTemp","value":"([\d\.]+)"
attr WP_Get reading01Name Raumtemp_Normal
attr WP_Get reading02Regex heatCircuit\[0\]\.param\.reducedSetTemp","value":"([\d\.]+)"
attr WP_Get reading02Name Raumtemp_Abgesenkt

attr WP_Get requestData [\
  {\
    "name": "APPL.CtrlAppl.sParam.heatCircuit[0].param.normalSetTemp"\
  },\
  {\
    "name": "APPL.CtrlAppl.sParam.heatCircuit[0].param.reducedSetTemp"\
  }
 
  etc. etc. etc. (ca 40 weitere Werte)
 
]
attr WP_Get requestHeader1 Content-Type: application/json
attr WP_Get requestHeader2 Accept: */*


und


[code]
define WP_Set HTTPMOD http://wp/var/readWriteVars?action=set
attr WP_Set enableControlSet 1
attr WP_Set enableCookies 1
attr WP_Set enforceGoodReadingNames 1
attr WP_Set handleRedirects 1
attr WP_Set requestHeader1 Content-Type: application/json
attr WP_Set requestHeader2 Accept: */*

attr WP_Set set1Data [{"name":"APPL.CtrlAppl.sParam.heatCircuit[0].param.normalSetTemp", "value":"$val"}]
attr WP_Set set1Name Raumtemp_Normal
attr WP_Set set2Data [{"name":"APPL.CtrlAppl.sParam.heatCircuit[0].param.reducedSetTemp", "value":"$val"}]
attr WP_Set set2Name Raumtemp_Abgesenkt

etc. etc. etc.....

[/code]

ch.eick

Zitat von: ansgru am 26 November 2022, 09:44:19
Ah und noch eine Frage: ich habe eine M-Tec Wärmepumpe die leider nur sehr begrenzte Modbusregister anbietet. Also frage ich alles via H Grundsätzlich läuft die Kommunikation wie folgt:
Moin,
ich habe nicht alles gelesen, Du kannst jedoch alles in ein Device unterbringen, also get und set und das auch noch in vielen Varianten.
Zusätzlich gibt es noch ein Follow* mit dem Du auch mehrere get oder set miteinander verketten kannst.

Beim define wird dann die Zeit auf 0 gesetzt

defmod WP_Get HTTPMOD http://wp/var/readWriteVars?languageCode=de 0

Das Scheduling mache ich dann über ein DOIF, was noch weitere Funktionalitäten für das Device abwickeln kann und es im FHEMWEB mit uiTable sehr schön Darstellen kann.

my5cent
    Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Aurel_B

Danke dir Christian, das FollowGet habe ich zwar gesehen, aber nicht im Zusammenhang mit diesem Verwendungszweck (mehrere Get Abfrage zusammen verknüpfen). Allerdings werden so nach meinem Verständnis immer noch einzelne Get Abfragen losgeschickt? Also quasi kein "Combine" wie bei Modbus sondern einfach alle verknüpften Anfragen nacheinander?

ch.eick

Zitat von: ansgru am 26 November 2022, 21:32:14
Danke dir Christian, das FollowGet habe ich zwar gesehen, aber nicht im Zusammenhang mit diesem Verwendungszweck (mehrere Get Abfrage zusammen verknüpfen). Allerdings werden so nach meinem Verständnis immer noch einzelne Get Abfragen losgeschickt? Also quasi kein "Combine" wie bei Modbus sondern einfach alle verknüpften Anfragen nacheinander?
Das ist richtig, jedoch werden sie synchronisiert und warten aufeinander.
Sollten alle Informationen auf einer Http Seite zusammen sein ist es natürlich besser nur einen Abruf zu starten.
Wenn man etwas setzt (set) kann man damit anschließend die Änderung wieder abfragen.

VG Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

StefanStrobel

Zitat von: ansgru am 26 November 2022, 09:44:19
Also quasi zusammengefasst: wie kann ich das Verhalten von HTTPMOD dem des Modbus Modules anpassen? 1 Register mit 1 Name welches gelesen und beschrieben werden kann und wo mehrere "Register" gebündelt mitgeschickt werden (damit nicht 40 einzelne Anfragen innerhalb kürzester Zeit auf die Wärmepumpensteuerung hereinprasseln)?

Hallo ansgru,

das geht leider nicht. Dazu sind die Web-Server zu unterschiedlich. In machen Fällen wie in Deinem wäre so etwas zwar denkbar, aber in vielen anderen versteht der Server eine solche Kombination von Anfragen nicht.

Ich würde an Deiner Stelle selbst mehrere gets definieren. Einen für die kombinierten Sachen, die häufig über das Intervall abgefragt werden und einen weiteren für die Kombination der anderen Werte, die nur selten abzufragen sind. Den würde ich dann separat per at o.ä. auslösen.

Gruss
   Stefan

Aurel_B

Ok, danke dir vielmals Stefan! Dann werde ich in Ruhe überlegen, welche Daten ich wie oft brauche und das auf entsprechende HTTPMOD Devices mit unterschiedlichen Polling-Intervalen verteilen.

ch.eick

Zitat von: ansgru am 27 November 2022, 22:52:54
Ok, danke dir vielmals Stefan! Dann werde ich in Ruhe überlegen, welche Daten ich wie oft brauche und das auf entsprechende HTTPMOD Devices mit unterschiedlichen Polling-Intervalen verteilen.
Wie bereits beschrieben geht das in einem Device und man macht dann ein separates Scheduling.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Aurel_B

Zitat von: ch.eick am 28 November 2022, 08:03:45
Wie bereits beschrieben geht das in einem Device und man macht dann ein separates Scheduling.

Hallo Christian,

oups, sorry, deinen Beitrag erst jetzt gesehen. Das Problem ist dann glaub ich, dass HTTPMOD die Anfragen nicht zusammenfassen kann. Ich habe im Moment ca. 40 Werte die ich regelmässig abfrage (werden noch mehr). Im Moment frage ich die Werte alle 20s alle zusammen ab (via "RequestData", siehe weiter oben). Für gewisse Werte reichen allerdings 5min, andere möchte ich alle paar Sekunden abfragen. D.h. dann auch, es würden alle paar Sekunden gleich mehrere POST Requests auf die arme Steuerung einprasseln wenn ich für jeden Wert eine separate Abfrage definiere :D Da splitte ich lieber meine HTTPMOD Devices in z.B. ein Device "HTTPMOD_5s", "HTTPMOD_1min" etc. und packe die gesammelten Anfragen dort rein -> kann dann immer noch bei Bedarf alles an einen Dummy senden damit ich alle Werte zentral habe. Oder ich bleibe bei einem Device und 1 RequestData mit allen Daten, dann liefert mir die Steuerung halt immer alle Werte. Da kann ich dann immer noch mit event-min-intervall o.Ä. die Events drosseln damit nicht alle 20s für jeden der 40 Werte ein Event ausgelöst wird.

Das geht mit Modbus ja alles viel einfacher und eleganter, ich verstehe die technischen Limitationen vom HTTPMOD Module (resp. das es keinen Standard gibt) und kann damit tiptop leben, braucht einfach ein Umdenken :-)

Beste Grüsse, Anton

blueberry63

Hallo,

ich habe hier nicht den kompletten Thread durchgelesen, möchte aber kurz mein Problem beschreiben.

Beim Auslesen einer JSON-API liefert mir HTTPMOD zeitweise keine Daten und zwar immer dann, wenn ein Status-Wert einen Umlaut enthält (ß). Daher habe ich es mit dem Attribut "bodyDecode=utf-8" probiert - ohne Erfolg.

Dann habe ich folgenden Tipp gelesen, bei dem der Code von "Utils.pm" verändert wird:


Zeile 34:
Code: [Auswählen]
#use Encode          qw(decode encode);
use Encode          qw(decode encode encode_utf8);
und Zeile 691:
Code: [Auswählen]
# my $decoded = eval { decode_json($buffer) };
my $decoded = eval { decode_json(encode_utf8($buffer)) };


Geht es auch ohne diese Code-Änderung? Könnte mir jemand auf die Sprünge helfen?

Gruß
Blueberry63
FHEM auf BBB mit Wheezy: 1x CUL_HM_HM_SCI_3_FM, 1x INSTAR CAM3010, 1x HM-LC-SW1-PL2, 1x HM-LC-Bl1PBU-FM, 1x HM-Sen-MDIR-O, Viessmann Heizung, Gaszähler via GPIO, Klingel via HM-LC-Bl1PBU-FM an FBox, Mailcheck, AVR, XBMC, NanoCUL 433+668 an Raspi per Ethernet, Funksteckdosen (Pollin, IT), Automower

Aurel_B

Hast du mal "bodyDecode utf8" ausprobiert? Resp. "(get|set|reading)[0-9]*Decode/Encode" und dann auch "utf8"?

blueberry63

FHEM auf BBB mit Wheezy: 1x CUL_HM_HM_SCI_3_FM, 1x INSTAR CAM3010, 1x HM-LC-SW1-PL2, 1x HM-LC-Bl1PBU-FM, 1x HM-Sen-MDIR-O, Viessmann Heizung, Gaszähler via GPIO, Klingel via HM-LC-Bl1PBU-FM an FBox, Mailcheck, AVR, XBMC, NanoCUL 433+668 an Raspi per Ethernet, Funksteckdosen (Pollin, IT), Automower