FHEM als Modbus Slave

Begonnen von SkyFox, 25 Januar 2016, 23:24:22

Vorheriges Thema - Nächstes Thema

ChrisD

Hallo,

Ich denke dass das umsetzbar ist. Da du die Registerbelegungen (und Formate) der beiden Geräte kennst sollte sich der Aufwand in Grenzen halten.

Grüße,

ChrisD

Guzzi-Charlie

Ok, Danke für die superschnelle Antwort.

Dann werde ich mir Dein Modul demnächst mal zu Gemüte führen und schauen ob ich was damit hinbekomme. Das heißt ich müßte dann das Modbus-Modul von Stefan Strobel zum Einlesen der Daten vom Zähler verwenden (das benutze ich jetzt schon für andere Modbus-Zähler) und dann Dein Modul als Slave mit einem weiteren USB-RS485 Stick als virtuellen Zähler den ich dann an meinen FEMS-Modbus hänge, oder? Und in FHEM mache ich dann lediglich ein Variablen-Mapping, oder?
- RaspPI 4+: (Cuno V2 -2x KS300, JeeLink -13x EC3000)
- Stromzähler (B+G E-Tech): 6x SDM120M, 9x XTM100A, 38x DRS110M
- LAN: IT LAN-Gateway mit 34x RMF-R1 (Rohrmotor24)
- WLAN: 85x Shelly, 12x Gosund SP111, 16x D1-Mini, 15x Sonoff Basic
- DECT: 6x DECT200, 8x DECT301, - HmIP: 3x FalmotC12, 16x WTH2

ChrisD

Hallo,

Wenn es ein fertiges Modul für deinen Zähler gibt solltest du dieses verwenden. Andernfalls kannst du das generische Modbus-Modul von Stefan Strobel einsetzen.

Das Mapping der Variablen erfolgt über die Kommentar-Funktion beim jeweiligen Gerät.

Grüße,

ChrisD

Guzzi-Charlie

Ob es für den vorgesehenen ABB B23 Zähler ein fertiges Modul gibt habe ich noch gar nicht geschaut. Für die anderen bisher von mir eingesetzten Zähler gab es nichts Fertiges. Da habe ich ein anderes Modul angepaßt.

"Kommentar-Funktion", ja stimmt habe ich ja in den Beiträgen schon gelesen. Hab mich nur bisher noch nicht damit beschäftigt. Da werden dann sicher noch einige Fragen auftauchen. Das dauert aber noch, da das FEMS noch nicht installiert ist. Heute ist der BYD-Batteriespeicher gekommen. Die ABB-Zähler kommen Morgen und die PV-Module sind auch schon da, aber die Unterkonstruktion fehlt noch.
- RaspPI 4+: (Cuno V2 -2x KS300, JeeLink -13x EC3000)
- Stromzähler (B+G E-Tech): 6x SDM120M, 9x XTM100A, 38x DRS110M
- LAN: IT LAN-Gateway mit 34x RMF-R1 (Rohrmotor24)
- WLAN: 85x Shelly, 12x Gosund SP111, 16x D1-Mini, 15x Sonoff Basic
- DECT: 6x DECT200, 8x DECT301, - HmIP: 3x FalmotC12, 16x WTH2

Klinki

Hi,
Hast Du Deine Modbus-Umsetzung eigentlich an den Start bekommen? Ich werde mich mit ähnlichen Thematiken auseinandersetzen. Zwar kein FEMS, aber dessen opensource-Ableger OpenEMS. Fhem hält bei mir eine ganze Menge an Stromzähler-Informationen vor - zumeist Impuls-Zähler.

Die Idee die Readings per Kommentar per Modbus zu Verfügung zu stellen, gefällt mir nicht so gut. Es setzt eine gute Strukturierung voraus, die man sich vorher überlegen muss. Eine doppelte Belegung von Slave-IDs oder Registern muss ausgeschlossen werden.

Aber es ist ja schon mal sehr schick überhaupt diese Möglichkeit zu haben!

Gruß,
Klinki

Guzzi-Charlie

Hallo,

inzwischen sind alle Zähler (auf verschiedenste Weise) eingebunden:

  • Die (2) Socomec E23 (Ertragszähler PV-Anlage 2+4), die per Modbus an FEMS hängen sind über HTTPMOD an FHEM angebunden
  • Der (1) Nova 80 (Ertragszähler PV-Anlage 1) ist per S0-Kopplung an den Photon-Datenlogger angebunden
  • Der (1) Nova 80 (Ertragszähler PV-Anlage 2) ist per S0-Kopplung mittels einem D1-Mini mit Tasmota-FW (+ Script) per MQTT an FHEM angebunden.
  • Der (1) Saia Burgess ALD1D5F (Einspeisezähler PV-Anlage 3) ist per S0-Kopplung mittels einem D1-Mini mit Tasmota-FW (+ Script) per MQTT an FHEM angebunden.
  • Die (6) B&G E-Tech XTM100A (Ertragszähler pro WR, PV-Anlage 1) sind per Modbus und RS485/USB-Stick (direkt am RasPi angesteckt) und über ein angepaßtes Modbus SDM220M-Modul an FHEM angebunden.
  • Die (3) B&G E-Tech SDM120M (Ertragszähler pro WR, PV-Anlage 2) sind per Modbus mittels einem D1-Mini mit Tasmota-FW (+ Script) per MQTT an FHEM angebunden.
  • Die (38) B&G E-Tech DRS110M (Stromkreiszähler) werden über die RS485-Schnittstelle (IEC1107-Protokoll) und RS485/USB-Stick (direkt am RasPi angesteckt) mittels Perl-Script (läuft auch auf dem FHEM-RasPi) abgefragt. Das Scrip überträgt dann minütlich die Daten per Telnet an FHEM (auch an dieser Stelle nochmal herzlichen Dank an CoolTux, der mich bei der Einbindung super unterstützt hat und ohne den ich das garantiert nicht hinbekommen hätte).
  • Die (2) ABB B23-100-112 (Wohnungs-Zwischenzähler) sind über Modbus mittels einem D1-Mini mit Tasmota-FW (+ Script) per MQTT an FHEM angebunden.
  • Die (3) ISKRA MT681 eHz  (Zweirichtungs Einspeise- und Bezugszähler) sind per optischer Schnittstelle mittels einem D1-Mini mit Tasmota-FW (+ Script) per MQTT an FHEM angebunden.

Die Zähler 3-5 werden wg. Eichablauf demnächst durch ABB B23-100-112 (3-phasig), bzw. B21-100-112 (1-phasig) ersetzt und dann ebenfalls per D1-Mini und MQTT an FHEM angebunden.

Zukünftige Projekte sind noch:

  • die Einbindung aller (6) Sensostar 2 Wärmemengenzähler (per optischer Schnittstelle/D1-Mini/MQTT)
  • das Auslesen der (2) Wasserzähler (per Kamera-Schnittstelle/D1-Mini/MQTT)
  • das Auslesen des (1) Gaszählers (entweder per Reed-Kontakt oder ebenfalls per Kamera-Schnittstelle/D1-Mini/MQTT)
  • Anbinden der (1) ABB Terra-AC Wallbox (per Modbus/D1-Mini/MQTT
  • Anbinden des zweiten BYD HVS-Speichers und des zugehörigen Goodwe ET8-WR's, die nicht am FEMS hängen (wie, weiß ich noch nicht)

- RaspPI 4+: (Cuno V2 -2x KS300, JeeLink -13x EC3000)
- Stromzähler (B+G E-Tech): 6x SDM120M, 9x XTM100A, 38x DRS110M
- LAN: IT LAN-Gateway mit 34x RMF-R1 (Rohrmotor24)
- WLAN: 85x Shelly, 12x Gosund SP111, 16x D1-Mini, 15x Sonoff Basic
- DECT: 6x DECT200, 8x DECT301, - HmIP: 3x FalmotC12, 16x WTH2

pdp1173

#66
Für eine dynamische Nulleinspeisung am Growatt SPH3600 brauche ich einen virtuellen SDM630 Leistungsmesser, dem ich selbst die Leistung mitgeben kann (3Phasen Netz mt 1 Phasen Inverter). Modbus Master zum Auslesen des Eastron SDM630 gibts einige, aber keinen für die Simulation eines solchen. Da alle Daten in FHEM vorhanden sind (SML Orbis Strommesser, Leistungsmesser Solar, etc.) habe ich dieses genial einfache Modul von ChrisD ausgesucht.  Der Growatt ist RTU Master und sucht den Energymeter auf Adresse #2. Er liest die ersten 18 Input Register. Ein einfacher Amazon USB-RS485 Stecker dient als Anschluß.

Leider hat der hier im Thread angebotene und auch der im Github vorhandene 36_ModbusSlave.pm einen Fehler, der den Betrieb mit dem Growatt unmöglich macht. Statt des Datensatzes der angekommen ist, wird nur das letzte Byte der Checksumme der Parse Routine übergeben, und die sendet dann ein 5 Byte Reply.

Fehlerhafter Code

sub ModbusSlave_Read($) {############################################################
# called from the global loop, when the select for hash->{FD} reports data
[color=red]Log 0[/color],"Read";
  my ($hash) = @_;
  my $buf = DevIo_SimpleRead($hash);
  return "" if(!defined($buf));

  my $name = $hash->{NAME};

  my $pdata = $hash->{helper}{PARTIAL};
  $pdata .= $buf;

  ModbusSlave_LogFrame($hash,"ModbusSlave_Read($name)",$pdata,4);

  if(( bytes::length($pdata) >= 4 ) && ( ModbusSlave_crc_is_ok($pdata)))
  {
    Log3 $hash,4,"ModbusSlave_Read($name) : crc ok, parsing request";
    RemoveInternalTimer( "RTimeout:".$name);
    $hash->{helper}{PARTIAL} = undef;
    ModbusSlave_UpdateStatistics($hash,1,0,bytes::length($buf),0);  #$buf ist letzter Block
    ModbusSlave_Parse($hash, $buf);  #$buf ist letzter Block, nicht ganzer Satz


Bei 9600baud und schnellem Rechner kommt der Datensatz nicht in einem Stück, sondern Zeichen- für Zeichen. Wahrscheinlich fällt der Fehler bei einem langsamen System mit hoher Baudrate gar nicht auf.

$buf = letzter Block von empfangenen Zeichen (hier: 2. Byte der Checksumme)
$pdata = Modbus Datenblock , der verarbeitet werden soll

Richtig  muss es also heissen:


    ModbusSlave_UpdateStatistics($hash,1,0,bytes::length($pdata),0);
    ModbusSlave_Parse($hash, $pdata);


Ausserdem "müllt" der Log über das Read bei Dauerabfragen das Logfile zu. Daher habe ich es auf verbose Level 2 gesetzt:


# called from the global loop, when the select for hash->{FD} reports data
  my ($hash) = @_;
  Log3 $hash,2,"Read RTU"


Danach läuft es jetzt einfach super, über MQTT2 hole ich die benötigten Werte für Spannung (wird nicht gebraucht) und natürlich die Leistung mit Vorzeichen. Die einfache Definition hier noch der Vollständigkeit:


root@mobilheim-esx:/opt/fhem# cat fhem.cfg

attr global userattr cmdIcon devStateIcon:textField-long devStateStyle icon sortby webCmd webCmdLabel:textField-long widgetOverride
attr global autoload_undefined_devices 1
attr global autosave 0
attr global logfile ./log/fhem-%Y-%m.log
attr global modpath .
attr global motd none
attr global statefile ./log/fhem.save
attr global verbose 3

define WEB FHEMWEB 8083 global
setuuid WEB 6327fbb8-f33f-9008-edc0-7d16279fe4a5412f

# Fake FileLog entry, to access the fhem log from FHEMWEB
define Logfile FileLog ./log/fhem-%Y-%m.log Logfile
setuuid Logfile 6327fbb8-f33f-9008-3f21-7401c05374272240

define autocreate autocreate
setuuid autocreate 63294800-f33f-9008-952b-d5effcc5fb36ae0b
attr autocreate filelog ./log/%NAME-%Y.log

define eventTypes eventTypes ./log/eventTypes.txt
setuuid eventTypes 6327fbb8-f33f-9008-164d-9139fc43c197395e

# Disable this to avoid looking for new USB devices on startup
#define initialUsbCheck notify global:INITIALIZED usb create

define MQTT2_Garage MQTT2_CLIENT 192.168.188.240:1883
setuuid MQTT2_Garage 6327fbb8-f33f-9008-1fbf-fad8914b9bc67ccc
attr MQTT2_Garage room Garage

define MQTT2_ewe MQTT2_DEVICE ewe
setuuid MQTT2_ewe 63294800-f33f-9008-39d9-e9b242ee7ccfda5a
attr MQTT2_ewe IODev MQTT2_Garage
attr MQTT2_ewe readingList garage/Strom/Strom/power:.* ewe_power\
  garage/Strom/Strom/power_L1:.* ewe_power_L1\
  garage/Strom/Strom/power_L2:.* ewe_power_L2\
  garage/Strom/Strom/power_L3:.* ewe_power_L3\
  garage/Growatt/Growatt/voltage:.* ewe_voltage
attr MQTT2_ewe room Garage



define SDM630 ModbusSlave /dev/ttyUSB1@9600,8,N,1
setuuid SDM630 63294800-f33f-9008-b320-ceb744d0d0fa80f9
attr SDM630 verbose 1

define SDM630_30001 dummy
setuuid SDM630_30001 63294800-f33f-9008-cd70-66f90b0318cc4025
attr SDM630_30001 comment MBR:2,0,I,,F
attr SDM630_30001 group SDM630
attr SDM630_30001 room SDM630

define SDM630_30003 dummy
setuuid SDM630_30003 63294800-f33f-9008-5876-b9d359d188945905
attr SDM630_30003 comment MBR:2,2,I,,F
attr SDM630_30003 group SDM630
attr SDM630_30003 room SDM630

define SDM630_30005 dummy
setuuid SDM630_30005 63294800-f33f-9008-d17b-b66dc1c0651e6d07
attr SDM630_30005 comment MBR:2,4,I,,F
attr SDM630_30005 group SDM630
attr SDM630_30005 room SDM630

define SDM630_30007 dummy
setuuid SDM630_30007 63294800-f33f-9008-5bda-716d0bc978966cd8
attr SDM630_30007 comment MBR:2,6,I,,F
attr SDM630_30007 group SDM630
attr SDM630_30007 room SDM630

define SDM630_30009 dummy
setuuid SDM630_30009 63294800-f33f-9008-8b30-de23e95b435476b6
attr SDM630_30009 comment MBR:2,8,I,,F
attr SDM630_30009 group SDM630
attr SDM630_30009 room SDM630

define SDM630_30011 dummy
setuuid SDM630_30011 63294800-f33f-9008-2043-c80a26a8d1ff9246
attr SDM630_30011 comment MBR:2,10,I,,F
attr SDM630_30011 group SDM630
attr SDM630_30011 room SDM630

define SDM630_30013 dummy
setuuid SDM630_30013 63294800-f33f-9008-6f26-2784b56ef96ab936
attr SDM630_30013 comment MBR:2,12,I,,F
attr SDM630_30013 group SDM630
attr SDM630_30013 room SDM630

define SDM630_30015 dummy
setuuid SDM630_30015 63294800-f33f-9008-2e00-979ffccc4ccc5d2b
attr SDM630_30015 comment MBR:2,14,I,,F
attr SDM630_30015 group SDM630
attr SDM630_30015 room SDM630

define SDM630_30017 dummy
setuuid SDM630_30017 63294800-f33f-9008-2d2d-8818d8fd079470c0
attr SDM630_30017 comment MBR:2,16,I,,F
attr SDM630_30017 group SDM630
attr SDM630_30017 room SDM630


#define sendtogrowatt at +00:00:10 { fhem "set SDM630_30013 " . ReadingsVal('MQTT2_ewe','ewe_power',0) }

define n_ewe_power notify MQTT2_ewe:ewe_power:.* { fhem "set SDM630_30013 " . ReadingsVal('MQTT2_ewe','ewe_power',0);;fhem "set SDM630_30001 " . ReadingsNum('MQTT2_ewe','ewe_voltage',0) }

setuuid n_ewe_power 63294800-f33f-9008-bda9-d0e2698a87eabef9
attr n_ewe_power room SDM630




30001 = Spannung an der 1. Leitung
30007 = Strom an der 1. Leitung
30013 = Leistung saldiert an der 1. Leistung +/-

Selbst setze ich FHEM schon lange Zeit auf Raspi ein, fremdle jedoch mit der PERL Sprache und vor allem der Syntax. Super mächtig aber manchmal für den non-Profi extrem nervig. Daher bisher wenig selbst gemacht. Ich bitte um Entschuldigung, wenn das Beispiel nicht für jeden optimal ist.

Eine "Unschönheit" des ModbusSlave Moduls: Da nicht global eine Adresse dem Slave zugeordnet wird, sondern nur in den Registern, antwortet der Slave manchmal (während der Testphase) auch auf Aufrufe mit anderen Adressen (#1, #3, etc.) . Das "verwirrte" manche Master, die einfach nach Teilnehmern auf dem Bus suchen (wie mein Growatt). Ein optionaler Parameter für die Slave Adresse wäre eine tolle Erweiterung, sodass das Modul bei allen anderen Adressen "den Mund hält". Ich sehe aber auch das Potential in der Lösung mit übergreifenden Registern. Danke für die Bereitstellung des Moduls.

ChrisD

Hallo,

Vielen Dank für den ausführlichen Fehlerbericht. Ich habe deine Korrekturen übernommen.

Den letzen Absatz habe ich nicht ganz verstanden. Die Adresse (Unit ID) kann mit angegeben werden, in deinem Beispiel ist dies auch der Fall (MBR:2,4,I,,F). Bei Anfragen auf nicht definierte Adressen, Register oder Coils antwortet das Modul mit einem Fehler. Möchtest du diese Fehlermeldung unterdrücken ?

Grüße,

ChrisD



pdp1173

Hallo, ich denke an das "diagslave" / "modpoll" Programm als Referenz. Dieses hat in der Start Command Line den Schalter "-a 2" (für ID 2) und kann dann mit beliebigen Daten beschickt werden, ohne zu reagieren. Das ist ja die Idee vom modBUS, dass mehrere Teilnehmer auf der gleichen 2-Draht-Leitung liegen und immer der, der angesprochen ist (also die ID stimmt), seine Sendeleitung auf die Leitung legen darf. Alle anderen müssen still bleiben. Realisiert ist das elektrisch in der RS485 mit 3-State Schaltern, die zwischen Empfangen/Senden/offen im Halb-Duplex schalten. Das wird heute fast nicht mehr gebraucht, meist ist der BUS eine Punkt-zu-Punkt Verbindung; das erspart viele elektrischen Probleme , die man damit haben kann. Wir haben heute LAN/Wifi-Netzwerke stattdessen , das hat sich damit eigentlich erledigt.

Zur Antwort auf deine Frage: Bei einer Anfrage, die zu keinem Register oder Coil passt, wäre IMHO das Richtige, einfach nicht zu antworten. Dennoch kann das auch so bleiben, da 99% der Fälle die Point-2-Point Situation ist.

Danke.

ChrisD

#69
Hallo,

Das aktuelle Verhalten ist auf einem seriellen Bus mit mehreren Teilnehmer in der Tat nicht sinnvoll.

Ich habe das Modul um das Attribut slaveAddress erweitert. Damit kann festgelegt werden auf welche Adresse(n) geantwortet werden soll. Wenn das Attribut nicht definiert ist wird wie bisher auf alles geantwortet. Beim Attribut kann entweder eine einzelne Adresse oder eine Regexp angegeben werden, z.B.:
attr mbslave slaveAddress [1|7|12]
Hier würde nur auf die Adressen 1, 7 und 12 geantwortet.

Grüße,

ChrisD

Die aktuelle Version kann hier heruntergeladen werden.

pdp1173

Klappt wunderbar, vielen Dank!

8)

Guzzi-Charlie

Hallo zusammen,

nach langer Abstinenz jetzt ein weiterer Fortschritt in Sachen "Anbindung an FHEM".

Der Punkt:
  • Anbinden des zweiten BYD HVS-Speichers und des zugehörigen Goodwe ET8-WR's, die nicht am FEMS hängen (wie, weiß ich noch nicht)

ist inzwischen erfolgreich abgehakt.
  • Sowohl die BYD HVS-Speicher lassen sich jetzt anbinden (mit dem FHEM-Modul "23_BYDBox.pm", Danke an MadMax dafür).
  • als auch die Goodwe-Wechselrichter der ET-Serie sind inzwischen integriert (über das fhempy-binding und das entsprechende fhempy-Modul "goodwe", Danke an dominik dafür).
    p.s. ==> über fhempy lassen sich auch Autos von KIA/Hyundai in FHEM integrieren.
- RaspPI 4+: (Cuno V2 -2x KS300, JeeLink -13x EC3000)
- Stromzähler (B+G E-Tech): 6x SDM120M, 9x XTM100A, 38x DRS110M
- LAN: IT LAN-Gateway mit 34x RMF-R1 (Rohrmotor24)
- WLAN: 85x Shelly, 12x Gosund SP111, 16x D1-Mini, 15x Sonoff Basic
- DECT: 6x DECT200, 8x DECT301, - HmIP: 3x FalmotC12, 16x WTH2