Neue Versionen und Support zum Modbus-Modul

Begonnen von StefanStrobel, 20 August 2017, 12:11:08

Vorheriges Thema - Nächstes Thema

bismosa

Hallo!

das ist bisher nicht viel:

defmod WP ModbusAttr 5 60 192.168.1.139:8899 TCP
attr WP dev-h-combine 10
attr WP dev-h-defPoll 1
attr WP obj-h60-len 4
attr WP obj-h60-reading day_energy
attr WP obj-h60-unpack (a4)
attr WP room PV


Ich hatte es auch mit

defmod WP ModbusAttr 3 60 192.168.1.139:8899 RTU

probiert...

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

pejonp

@Bismosa

Stimmt die Modbus Adresse? Du hast einmal die 5 und dann die 3!?

Per Python kannst du etwas auslesen?


Pejonp
LaCrossGW 868MHz:WT470+TFA+TX37-IT+EMT7110+W136+WH25A HP1003+WH2621
SignalD(CC1101):Bresser+WS-0101(868MHz WH1080)+Velux KLF200+MAX!+HM-MOD-UART:Smoke HM-SEC-SD+VITOSOLIC 200 RESOL VBUS-LAN+SolarEdge SE5K(Modbus)+Sonnen!eco8(10kWh)+TD3511+DRT710M(Modbus)+ZigBee+Z-Wave+MQTT+vitoconnect

bismosa

Hallo!

Die 5 und die 3 habe ich aus deinen Beispielen verwendet.
Ich glaube so einfach ist das Auslesen nicht. Weitere Infos gibt es hier:
https://pysolarmanv5.readthedocs.io/en/stable/solarmanv5_protocol.html

Ich glaube mir ist das dann doch etwas zu kompliziert. Da nutze ich dann doch lieber das fertige Python script und lasse mir die Daten per MQTT an FHEM senden.

Vielen Dank für die Hilfsbereitschaft!

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

StefanStrobel

Das Solarman-Protokoll scheint kein Modubs zu sein sondern ein proprietäres Protokoll, bei dem Modbus-Frames nach einem eigenen Header eingefügt werden können ...

Gruss
   Stefan

StefanStrobel

Anbei eine neue Version des Moduls zum Testen bevor ich es einchecke und es per update verteilt wird.
Man kann nun custom function codes selbst definieren, das Loglevel wurde bei einigen Events von 3 auf 4 erhöht und ein par Bugs gefixt.
Zudem sind einige Data types vordefiniert, so dass man meist keinen unpack code und keine len mehr angeben muss und der data type reicht.
Ich hoffe es funktioniert noch alles :-)

Gruss
   Stefan

Roger

#1115
Zitat von: StefanStrobel am 11 März 2023, 16:46:53
Anbei eine neue Version des Moduls zum Testen bevor ich es einchecke und es per update verteilt wird.
Man kann nun custom function codes selbst definieren, das Loglevel wurde bei einigen Events von 3 auf 4 erhöht und ein par Bugs gefixt.
Zudem sind einige Data types vordefiniert, so dass man meist keinen unpack code und keine len mehr angeben muss und der data type reicht.
Ich hoffe es funktioniert noch alles :-)
Gruss Stefan

Hi Stefan,
soll in dieser Version auch die dev-fc Erweiterung funktionieren?

Lesen/get von den Geräten klappt. Bei Ausführung vom set-Befehl erhalte ich:
2023.03.11 17:32:48.275 1: PERL WARNING: Use of uninitialized value $newType in substitution (s///) at 01_FHEMWEB.pm line 2377.
2023.03.11 17:32:48.277 1: PERL WARNING: Use of uninitialized value $newType in string ne at 01_FHEMWEB.pm line 2378.
2023.03.11 17:32:48.280 1: PERL WARNING: Use of uninitialized value $oldType in string ne at 01_FHEMWEB.pm line 2378.
Undefined subroutine &Modbus::HexIfNeeded called at 98_Modbus.pm line 2546.

und FHEM ist weg.

//Roger
Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

StefanStrobel

Ah, sorry - da gehört auch eine neue Version der Utils dazu.
Die muss wie üblich nach lib/FHEM/HTPMOD/

Gruss
  Stefan

Roger

So jetzt läuft es.  :)
Habe die Dateien auf allen meine FHEM-Servern und -Instanzen ersetzt - bisher nichts Auffälliges.

//Roger
Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

Mad-at

#1118
Hallo!

Ich würde ein wenig Hilfe brauchen. Ich habe erfolgreich meine drexel&weiss stratos mittels ModBus/ModbusAttr in FHEM integriert. Werte Lesen funktioniert einwandfrei. Aber beim Schreiben des Registers h5002, das ich korrekt auslesen kann, bekomme ich einen Error "illegal data value" ("Schreib- / lesezugriff auf Parameter verweigert, Wert ausserhalb des Bereichs") - siehe Log ganz unten (ich habs mit LF umgeben damit man es besser findet).
Ich verstehe nicht, warum Auslesen korrekt klappt, aber Setzen nicht? (Das Register ist explizit zum Schreiben gedacht). Wenn er vom aus dem Register gelesenen gelieferten Hexcode zum richtigen Wert kommt, müsste doch der Weg zurück auch klappen?
Edit: Es ist FC16 - würde das aber nicht durch "len 2" ohnehin vorgegeben? /Edit (ja es wird eh als FC16 geschrieben siehe Log)

Vielleich hat jemand einen Tipp?

Hier ein List des Devices:

Internals:
   DEF        0 60 192.168.1.201:8899 TCP
   DeviceName 192.168.1.201:8899
   EXPECT     idle
   FD         4
   FUUID      640a1936-f33f-db1a-c548-fc2cdc36d517c360
   IODev      DrexelWeissStratos
   Interval   60
   LASTOPEN   1678704516.98814
   LeadingZeros 1
   MODBUSID   0
   MODE       master
   MODULEVERSION Modbus 4.4.14 - 30.1.2023
   NAME       DrexelWeissStratos
   NOTIFYDEV  global
   NR         1427
   NTFY_ORDER 50-DrexelWeissStratos
   PARTIAL   
   PROTOCOL   TCP
   STATE      opened
   TCPConn    1
   TYPE       ModbusAttr
   devioLoglevel 3
   eventCount 36
   nextOpenDelay 60
   Helper:
     DBLOG:
       AktuelleLuefterstufe:
         DBLogging:
           TIME       1678704879.74361
           VALUE      min
       CO2_Raumluft:
         DBLogging:
           TIME       1678704879.54451
           VALUE      633.0 ppm
       Luefterstufe_setzen:
         DBLogging:
           TIME       1678704879.94239
           VALUE      auto
       TemperaturAussenluft:
         DBLogging:
           TIME       1678704879.34492
           VALUE      15.1 °C
       TemperaturRaumluft:
         DBLogging:
           TIME       1678704879.14493
           VALUE      22.4 °C
       state:
         DBLogging:
           TIME       1678704518.90177
           VALUE      CONNECTED
   QUEUE:
   READ:
     BUFFER     
   READINGS:
     2023-03-13 11:54:39   AktuelleLuefterstufe min
     2023-03-13 11:54:39   CO2_Raumluft    633.0 ppm
     2023-03-13 11:54:39   Luefterstufe_setzen auto
     2023-03-13 11:54:39   TemperaturAußenluft 15.1 °C
     2023-03-13 11:54:39   TemperaturRaumluft 22.4 °C
     2023-03-13 11:48:38   state           opened
   REMEMBER:
     lid        0
     lname      DrexelWeissStratos
     lrecv      1678704879.94071
     lsend      1678704879.84382
   defptr:
     DrexelWeissStratos 0
   gotReadings:
     Luefterstufe_setzen auto
   lastRead:
     h00200     1678704879.14401
     h00202     1678704879.34399
     h00230     1678704879.54361
     h01066     1678704879.74289
     h05002     1678704879.94193
Attributes:
   dev-h-write 6
   dev-timing-timeout 2.6
   obj-h00200-expr $val / 1000
   obj-h00200-format %.1f °C
   obj-h00200-len 2
   obj-h00200-poll 1
   obj-h00200-reading TemperaturRaumluft
   obj-h00200-revRegs 1
   obj-h00202-expr $val / 1000
   obj-h00202-format %.1f °C
   obj-h00202-len 2
   obj-h00202-poll 1
   obj-h00202-reading TemperaturAußenluft
   obj-h00202-revRegs 1
   obj-h00230-format %.1f ppm
   obj-h00230-len 2
   obj-h00230-poll 1
   obj-h00230-reading CO2_Raumluft
   obj-h00230-revRegs 1
   obj-h01066-len 2
   obj-h01066-map 0:aus, 1:min, 2:normal, 3:max
   obj-h01066-poll 1
   obj-h01066-reading AktuelleLuefterstufe
   obj-h01066-revRegs 1
   obj-h05002-allowWrite 1
   obj-h05002-hint aus,min,normal,max,auto,party
   obj-h05002-len 2
   obj-h05002-map 0:aus, 1:min, 2:normal, 3:max, 4:auto, 5:party
   obj-h05002-max 5
   obj-h05002-min 0
   obj-h05002-poll 1
   obj-h05002-reading Luefterstufe_setzen
   obj-h05002-revRegs 1
   obj-h05002-set 1
   room       Heizung
   userReadings Luefterstufe_setzen:aus,min,normal,max,auto,party
   verbose    1
   webCmd     Luefterstufe_setzen



2023.03.12 15:15:03 4: DrexelWeissStratos: set called with Luefterstufe_setzen (h05002) setVal = 1
2023.03.12 15:15:03 5: DrexelWeissStratos: GetSetChecks with force
2023.03.12 15:15:03 5: DrexelWeissStratos: GetSetChecks returns success
2023.03.12 15:15:03 5: DrexelWeissStratos: checkRange for FormatSetVal checks 1 against min 0
2023.03.12 15:15:03 5: DrexelWeissStratos: checkRange for FormatSetVal checks 1 against max 5
2023.03.12 15:15:03 5: DrexelWeissStratos: set packed hex 31 with n to hex 0001
2023.03.12 15:15:03 4: DrexelWeissStratos: DoRequest called from SetLDFn created new request, read buffer empty,
request: id 0, write fc 16 h05002, len 2, value 0001, tid 189, master device DrexelWeissStratos, reading Luefterstufe_setzen (set Luefterstufe_setzen)
2023.03.12 15:15:03 5: DrexelWeissStratos: QueueRequest called from DoRequest with h05002, qlen 0 from master DrexelWeissStratos through io device DrexelWeissStratos
2023.03.12 15:15:03 5: DrexelWeissStratos: ProcessRequestQueue called from QueueRequest as direct:DrexelWeissStratos, qlen 1, force, request: request: id 0, write fc 16 h05002, len 2, value 0001, tid 189, master device DrexelWeissStratos, reading Luefterstufe_setzen (set Luefterstufe_setzen), queued 0.00 secs ago
2023.03.12 15:15:03 5: DrexelWeissStratos: checkDelays busDelayRead, last activity on bus was 21.163 secs ago, required delay is 0
2023.03.12 15:15:03 5: DrexelWeissStratos: checkDelays sendDelay, last send to same device was 21.259 secs ago, required delay is 0.1
2023.03.12 15:15:03 5: DrexelWeissStratos: checkDelays commDelay, last communication with same device was 21.163 secs ago, required delay is 0.1
2023.03.12 15:15:03 5: DrexelWeissStratos: checkDelays clientSwitchDelay is not relevant
2023.03.12 15:15:03 4: DrexelWeissStratos: ProcessRequestQueue (V4.4.14 - 30.1.2023) qlen 1, sending 00bd000000090010138a0002040001 via 192.168.1.201:8899, read buffer empty,
request: id 0, write fc 16 h05002, len 2, value 0001, tid 189, master device DrexelWeissStratos, reading Luefterstufe_setzen (set Luefterstufe_setzen), queued 0.00 secs ago
2023.03.12 15:15:03 5: DrexelWeissStratos: Send called from ProcessRequestQueue
2023.03.12 15:15:03 5: DevIo_SimpleWrite DrexelWeissStratos: 00bd000000090010138a0002040001
2023.03.12 15:15:03 5: DrexelWeissStratos: ReadAnswer called from SetLDFn
2023.03.12 15:15:03 5: DrexelWeissStratos: ReadAnswer remaining timeout is 2.5950779914856
2023.03.12 15:15:04 5: DrexelWeissStratos: ReadAnswer got: 00bd00000003009003
2023.03.12 15:15:04 5: DrexelWeissStratos: ParseFrameStart called from ReadAnswer
2023.03.12 15:15:04 4: DrexelWeissStratos: ParseFrameStart (TCP, master) extracted id 0, fCode 144, tid 189, dlen 3 and potential data 03
2023.03.12 15:15:04 5: DrexelWeissStratos: HandleResponse called from ReadAnswer
2023.03.12 15:15:04 5: DrexelWeissStratos: ParseResponse called from HandleResponse


2023.03.12 15:15:04 4: DrexelWeissStratos: HandleResponse got response with error code 90 / 03, illegal data value


2023.03.12 15:15:04 4: DrexelWeissStratos: HandleResponse done, current frame / read buffer: 00bd00000003009003, fCode 144, tid 189,
request: id 0, write fc 16 h05002, len 2, value 0001, tid 189, master device DrexelWeissStratos, reading Luefterstufe_setzen (set Luefterstufe_setzen), queued 0.10 secs ago, sent 0.10 secs ago,
response: no id, fc 144, error code 03, len 2
2023.03.12 15:15:04 5: DrexelWeissStratos: ResetExpect for HandleResponse from response to idle
2023.03.12 15:15:04 5: DrexelWeissStratos: DropFrame called from ReadAnswer - drop 00bd00000003009003
2023.03.12 15:15:04 5: DrexelWeissStratos: set is sending read after write
2023.03.12 15:15:04 4: DrexelWeissStratos: DoRequest called from SetLDFn created new request, read buffer empty,
request: id 0, read fc 3 h05002, len 2, tid 138, master device DrexelWeissStratos, reading Luefterstufe_setzen (set Luefterstufe_setzen Rd),
response: no id, no fcode


Edit2: Er schreibt ja "00bd000000090010138a0002040001". Sollte Er nicht eigentlich eher so etwas wie 00bd000000090010138a00020400000001 schreiben? Er muss doch zwei Register füllen? 138a ist das Register, dann 0002 für 2 Register, 04 für 4 Bytes die er schreiben will, dann kommen aber nur 2 Bytes nämlich 00 01. Verstehe ich nicht.  /Edit2

Falls benötigt:
Hier sind die Register dokumentiert: https://github.com/diresi/drexel-und-weiss/blob/master/900.6667_00_TI_Modbus_Parameter_V4.01_DE.pdf

Hier ist die Modbus Implementation von Drexel und Weiss dokumentiert: https://gasserenergy.ch/wp-content/uploads/2015/09/900.6660_01_TI_Modbus_RTU_DE.pdf

Danke!

Matthias

Aurel_B

Hallo Matthias, kennst du QModMaster https://sourceforge.net/projects/qmodmaster/? Ist ein super hilfreiches Tool für Modbus Verbindungen zu untersuchen. Wann immer ich ein komisches Modbusgerät habe teste ich es zuerst mit QModMaster da man damit nach einer kurzen Eingewöhnungszeit sehr rasch "rumspielen" kann. Es ist ein Monitor dabei, dort siehst du die übertragenen Bytes und die Antworten. So kannst du herausfinden, was dein DrexelWeissStratos genau möchte damit kein Fehler zurückgemeldet wird.

Beste Grüsse, Anton

Mad-at

#1120
Vielen Dank Anton!
Kannte ich nicht!
Tatsächlich kann ich die Register damit korrekt lesen:
[TCP]>Rx > 17:09:28:782 - 00  22  00  00  00  07  00  03  04  00  00  00  04 
und schreiben - und das Payload Muster ist genau jenes welches ich oben im Post schon "gewünscht" hatte: 00 00 00 0x


[TCP]>Tx > 17:13:04:916 - 00  29  00  00  00  0B  00  10  13  8A  00  02  04  00  00  00  04 
[TCP]>Rx > 17:13:05:084 - 00  29  00  00  00  06  00  10  13  8A  00  02 
Sys > 17:13:05:084 - values written correctly.
[TCP]>Tx > 17:21:36:754 - 00  2B  00  00  00  0B  00  10  13  8A  00  02  04  00  00  00  00 
[TCP]>Rx > 17:21:37:064 - 00  2B  00  00  00  06  00  10  13  8A  00  02 
Sys > 17:21:37:064 - values written correctly.


Und die DrexelWeiss richtet sich auch danach...  ;)

Aber wie entlocke ich das ModBusAttr? Das scheint unbedingt 00 0x schreiben zu wollen, obwohl len2 gesetzt ist und es dementsprechend korrekt FC16 meldet.

Auffällig auch: er will anscheinend dass das Register zuerste gelesen wird und dann geschrieben? Zumindest mit QModMaster gibt er mir sonst "invalid data". Manuell Lesen mit ModBusAttr und dann schreiben hilft aber nicht...

LG
Matthias


Aurel_B

Hmmm, hast du schon die unpack Option ausprobiert? Ich bin da zu wenig tief in der Materie drin, vielleicht hilft aber ein obj-h05002-unpack l ? Also l für long == 32bit, weil bei dir werden ja nur 16bit übertragen beim Set Befehl, also 00 0x statt 00 00 00 0x.

Das mit dem Register zuerst lesen und erst dann schreiben finde ich komisch. Wenn du direkt ein "set" absetzt mit QModMaster reklamiert er? Wie ist genau der Vorgang?

Mad-at

#1122
Ja, aber unpack l liefert beim Lesen 1024 anstelle von 4
unpack n liefert zusammen mit revregs 1 die derzeit richtige Antwort (00eb0000000700030400000004), aber ich bin beim Setzen (in diesem Fall von 0) wieder bei einem dem ursprünglichen Poblem sehr ähnlichen: "sending 0026000000090010138a0002040000" und bekomme zurück "HandleResponse got response with error code 90 / 03, illegal data value"

Mit QModMaster:
[TCP]>Tx > 15:14:47:267 - 00  10  00  00  00  0B  00  10  13  8A  00  02  04  00  00  00  00 
[TCP]>Rx > 15:14:47:372 - 00  10  00  00  00  06  00  10  13  8A  00  02
Sys > 15:14:47:372 - values written correctly.

Das mit dem read before write bei QmodMaster vergiss bitte wieder, Fehler zwischen Bildschirm und Tastatur  ;)

Aber vielleicht mache ich einen grundsätzlichen Fehler: Ich habe RevRegs aktiviert, weil FHEM mir sonst keine Werte ausspuckt. Wenn ich das Log aber nochmal genau anschaue, dann darf ich eigentlich nicht revRegs machen:

2023.03.19 15:19:36 5: DrexelWeissStratos: ParseDataString called from HandleResponse with data hex 00000004, type h, adr 05002, op read
2023.03.19 15:19:36 5: DrexelWeissStratos: SplitDataString called from ParseDataString with data hex 00000004, type h, adr 05002, valuesLen 2, op read
2023.03.19 15:19:36 5: DrexelWeissStratos: CreateDataObjects called from ParseDataString with objList h05002
2023.03.19 15:19:36 5: DrexelWeissStratos: CreateDataObjects sortedList h05002
2023.03.19 15:19:36 5: DrexelWeissStratos: CreateParseInfoCache called
2023.03.19 15:19:36 5: DrexelWeissStratos: ReverseWordOrder is reversing order of up to 2 registers

2023.03.19 15:19:36 5: DrexelWeissStratos: ReverseWordOrder for CreateDataObjects is transforming 00000004 to 00040000

2023.03.19 15:19:36 5: DrexelWeissStratos: CreateDataObjects unpacked 00040000 with n to 4
2023.03.19 15:19:36 5: DrexelWeissStratos: MapConvert called from CreateDataObjects converted 4 (4) to auto with map 0:aus, 1:min, 2:normal, 3:max, 4:auto, 5:party
2023.03.19 15:19:36 4: DrexelWeissStratos: CreateDataObjects assigns value auto to Luefterstufe_setzen
2023.03.19 15:19:36 5: DrexelWeissStratos: ParseDataString created 1 readings
2023.03.19 15:19:36 4: DrexelWeissStratos: HandleResponse done, current frame / read buffer: 00810000000700030400000004, fCode 3, tid 129,
request: id 0, read fc 3 h05002, len 2, tid 129, master device DrexelWeissStratos, reading Luefterstufe_setzen (getUpdate for Luefterstufe_setzen len 2), queued 2.20 secs ago, sent 0.11 secs ago,
response: no id, fc 3, h05002, len 2, values 00000004

Also habe ich das Ganze jetzt folgendermaßen zu Fuß gelöst:

revRegs 0
unpack H*

Damit bekomme ich die raw hex Werte, das ist vielleicht nicht so schön, aber lässt sich mit einem map wunderschön ausblenden. Und siehe da: jetzt kann ich auch korrekt setzen :)
Vielen Dank für Deine Hilfe und den entscheidenden Denkanstoß!

Aurel_B

Es freut mich zu hören, dass es zumindest mit raw Hex und map geklappt hat :-) Tönt für mich weiterhin ein wenig nach einer pack/unpack & Endian Geschichte. Wenn es mit Hex klappt kann man es ja auch so laufen lassen ;-)

StefanStrobel

Hallo zusammen,

H* und map ist sicher ein gangbarer Weg, wenn es eh nur um ein paar mögliche Werte geht. Bei echten Messwerten braucht man aber doch den richtigen unpack-Code und ,,n" ist definitiv falsch, da n für unsigned short (16 Bit) steht und ein Code für 32 Bit benötigt wird. ,,l" steht für signed long (32 Bit), aber naheliegender wäre z.B. ,,L>" oder ,,L<,, für unsigned long in big bzw. little endian form.
Siehe https://perldoc.perl.org/functions/pack

Da hier jedes Gerät seine Daten anders darstellt, muss man das testen.

In der neuen Version des Moduls kann man übrigens auch statt unpack code und length direkt einen Typ wie ,,unsigned long little" oder ,,unsigned long big" angeben.
Z.B. attr obj-h5002-type unsigned long big
unpack code und len sollten dann weggelassen werden, da sie den type überschreiben würden.


Gruß
    Stefan