Wago /SPS über Modbus(TCP/IP) in FHEM steuern

Begonnen von lechez, 05 Mai 2013, 10:50:13

Vorheriges Thema - Nächstes Thema

lechez

Selber gelöst :)

Ich sollte so früh nicht schon anfangen  ;D.

Ich hab ja das flasche Register angesprochen mit 40001  geht es. .:)

Danke ChrisD für die tolle Weiterentwicklung!

Gruß
lechez

qwikser

Hallo,

wie bereits erwähnt hatte ich ja mein MAX! System mit der "99_modbus.pm & MBclient.pm" an meine  Wago weiter geleitet.
Da dies aber fhem beim "Update" der Daten so arg strapaziert, wollte ich es jetzt auch mal mit dem "36_ModbusTCPServer.pm" probieren.
Einzelne Bits mit "37_ModbusCoil.pm" und auch ganze bytes mit "37_ModbusRegister.pm" funktioniert wunderbar.

Nur habe ich jetzt das Problem, dass ich nicht so recht weiß wie ich das jetzt mit den MAX! Daten in fhem verknüpfen soll.  ???

Hier mal ein Beispiel vom "MBclient.pm"
1.

define stellmotor_temp_soll_kueche dummy
attr stellmotor_temp_soll_kueche group Küche
attr stellmotor_temp_soll_kueche room Wago
attr stellmotor_temp_soll_kueche stateFormat state °C
define at_write_stellmotor_temp_soll_kueche at +*00:01:00 {write_modbus(12300,ReadingsVal("MAX_008695","state", 0)*10)}
define at_read_stellmotor_temp_soll_kueche at +*00:05:05 {fhem("set stellmotor_temp_soll_kueche ".read_modbus_zaehler(12300)/10)}

2.

define haustuer_aufzu_flur dummy
attr haustuer_aufzu_flur group Flur
attr haustuer_aufzu_flur room Wago
define act_haustuer_aufzu_flur notify MAX_0850c2:onoff.* {write_modbus_coil(12943,$EVTPART1)}
define at_read_haustuer_aufzu_flur at +*00:05:05 {fhem("set haustuer_aufzu_flur ".((read_modbus_coil(12943) eq "on")?"Offen":"Geschlossen"))}

3.

define Steckdose_A_wago_EIN dummy
attr Steckdose_A_wago_EIN group Ventilator Schlafzimmer
attr Steckdose_A_wago_EIN room Funker-Sender
define at_read_Steckdose_A_wago_EIN at +*00:00:03 {fhem("set Steckdose_A_wago_EIN ".((read_modbus_coil(13088) eq "on")?"AKTIV":"INAKTIV"))}
define NSteckdose_A_wago_EIN notify Steckdose_A_wago_EIN { if ( Value("Steckdose_A_wago_EIN") eq "AKTIV" ) {system("sudo /home/pi/pilight/pilight-send -p elro_he -s 31 -u 1 -t");;} }



.. mit dem 3ten Beispiel schalte ich mit einem Funkmodul am Raspberry eine Funksteckdose aus dem Baumarkt.

Vielen dank schon mal im voraus
MfG.
Daniel

ChrisD

Hallo,

Hier ein möglicher (aber nicht ganz ausgetesteter) Vorschlag für die Übertragung:

1.
define stellmotor_temp_soll_kueche ModbusRegister 0 12300
attr stellmotor_temp_soll_kueche conversion 0.1:0
attr stellmotor_temp_soll_kueche group Küche
attr stellmotor_temp_soll_kueche room Wago
attr stellmotor_temp_soll_kueche stateFormat state °C
attr stellmotor_temp_soll_kueche disableRegisterMapping 1
define NMAX_008695_to_Wago notify MAX_008695 set stellmotor_temp_soll_kueche $EVTPART1


2.
define haustuer_aufzu_flur ModbusCoil 0 12943
attr haustuer_aufzu_flur disableRegisterMapping 1
attr haustuer_aufzu_flur group Flur
attr haustuer_aufzu_flur room Wago
define act_haustuer_aufzu_flur notify MAX_0850c2:onoff.* set haustuer_aufzu_flur $EVTPART1


3.
define Steckdose_A_wago_EIN ModbusCoil 0 13088
attr Steckdose_A_wago_EIN disableRegisterMapping 1
attr Steckdose_A_wago_EIN event-on-change-reading state
attr Steckdose_A_wago_EIN eventMap off:INAKTIV on:AKTIV
attr Steckdose_A_wago_EIN group Ventilator Schlafzimmer
attr Steckdose_A_wago_EIN room Funker-Sender
define NSteckdose_A_wago_EIN notify Steckdose_A_wago_EIN { if ( Value("Steckdose_A_wago_EIN") eq "AKTIV" ) {system("sudo /home/pi/pilight/pilight-send -p elro_he -s 31 -u 1 -t");;} }


Die Übertragung unterscheidet sich nicht allzuviel von deiner bisherigen Version, lediglich die Syntax ändert sich. Du musst weiterhin die Zuweisung über notify machen.

Wie häufig ein Wert von der SPS gelesen wird kann über das Attribut updateIntervall in Sekunden eingestellt werden, z.B.
attr stellmotor_temp_soll_kueche updateIntervall 305 für 5:05. Default ist 0.1 (also 100 ms). Falls dieser Wert kleiner ist als das Attribut pollIntervall des Serverbausteines, hat der Wert des Serverbausteines Vorrang. Default beim Serverbaustein ist 3 s.

Ich habe eine experimentelle Version von 36_ModbusTCPServer welche ohne externes notify auskommt, allerdings ist sie noch nicht ganz ausgereift und die Konfiguration ist etwas komplizierter.

Grüße,

ChrisD

qwikser

#198
Hallo ChrisD,

einfach der Wahnsinn wie du immer direkt zur Stelle bist wenn jemand Hilfe braucht, HUT AB!

Habe mal einfach alles ins fhem kopiert. Zum ersten "Paket", der Sollwert Übertragung ist es jetzt so, dass ich in der SPS kurz sehe das er was schreibt, es aber dann direkt wieder auf 0 geschrieben wird.

Der Stellmotor im MAX! liefert mir diese Readings die ich weiterleiten will:
"battery - ok" "desiredTemperature - 17.0" "temperature - 20.1"
Ich denke das in deinem Code

define NMAX_008695_to_Wago notify MAX_008695 set stellmotor_temp_soll_kueche $EVTPART1

noch irgendwo der Aufruf zu einem der oben genannten Readings fehlt.
Vielleicht so?

define NMAX_008695_to_Wago notify MAX_008695 set stellmotor_temp_soll_kueche:(temperature)


Das 2te "Packet" mit dem Magnetkontakt geht leider auch nicht. Als Reading lieftert dieser mir übrigens "onoff - 1"  Also 1 für offen 0 für zu.
Das 3te "Packet" mit der Steckdose funktionierte auf Anhieb. ;D

MfG.

ChrisD

Hallo,

Im notify für den Sollwert fehlt das Reading das weitergeleitet werden soll. So sollte es gehen:

define NMAX_008695_to_Wago notify MAX_008695:desiredTemperature.* set stellmotor_temp_soll_kueche $EVTPART1

Das Reading (desiredTemperature) welches übertragen werden soll kommt nach dem Namen des Devices (MAX_008695).

ModbusCoil unterstützt die Werte 0 und 1 nicht, deshalb funktioniert der Türkontakt nicht. Ich werde dies nachrüsten. Bis dahin sollte dies funktionieren:
define act_haustuer_aufzu_flur notify MAX_0850c2:onoff.* {fhem "set haustuer_aufzu_flur ".($EVTPART1==1?"on":"off")}


Grüße,

ChrisD

qwikser

Hi Chris,

danke, deine Tipps haben prima funktioniert!!
..habe jetzt (gestern und heute) soweit fast  ::) alles mit dem "neuen" Modul angepasst, und es läuft um längen besser als das "alte".. auch Fhem lässt sich jetzt wieder im WebInterface bedienen.  :P

Habe jetzt nur noch das Problemchen mit der Lautstärke Anpassung eines StreamRadios von meiner Wago aus.
Der alte Code sah so aus:

define radio_volume dummy
attr radio_volume group Radio via Wago
attr radio_volume room Media
attr radio_volume stateFormat state %
define at_read_radio_volume at +*00:00:05 {fhem("set radio_volume ".read_modbus_zaehler(12343))}
define Nradio_volume notify radio_volume {\
my $vol = Value("radio_volume");;\
fhem "set SRadio VOLUME $vol";;\
}


Aktuell sieht mein Versuch so aus:

define radio_volume ModbusRegister 0 12343
attr radio_volume disableRegisterMapping 1
attr radio_volume room Media
attr radio_volume group Radio
attr radio_volume alias Volume
attr radio_volume stateFormat state %
define Nradio_volume notify radio_volume $EVTPART1 {my $vol = ( Value("radio_volume") ) {fhem ("set SRadio VOLUME $vol");;} }


Der Wert wird auch schon richtig aus der SPS gelesen, nur wird der Befehl zur Anpassung der Lautstärke nicht ausgeführt.  :-\

Danke schon mal im Voraus!

ChrisD

Hallo,

Versuch mal das notify so zu ändern:
define Nradio_volume notify radio_volume set SRadio VOLUME $EVTPART0

Zusätzlich musst du noch das Attribut event-on-change-reading von radio_volume setzen:
attr radio_volume event-on-change-reading state

Damit sollte die Lautstärke wie gewünscht übertragen werden.

Da die Werte vom Modbus regelmäßig gelesen werden sollte das Attribut event-on-change-reading bei allen Registern und Coils gesetzt sein. Dadurch werden nur Ereignisse erzeugt wenn sich der Wert ändert.

Grüße,

ChrisD

qwikser

#202
Hallo Chris,

vielen Dank!! ..dein Tipp hat wie gewöhnlich super geklappt!  ;D
Wollte jetzt noch ein paar IP Adressen im Netzwerk abfragen und auf einzelne Coils in meine SPS bringen, nur scheitere Ich wie gewöhnlich auch dadran..  ::)

Aktuell sieht es so aus:

#-------------------------------------------------------------------------------------------------------------------------------------------------------- Wago <-> iPs Netzwerk
define HandyDina PRESENCE lan-ping 192.168.178.13 10
attr HandyDina alias iPhone Carina
attr HandyDina eventMap absent:INAKTIV present:AKTIV
attr HandyDina group Smartphones
attr HandyDina room IP Überwachung
#----------------------------------------------------------------------------------------------
define HandyDina_WAGO ModbusCoil 0 13216
attr HandyDina_WAGO disableRegisterMapping 1
attr HandyDina_WAGO event-on-change-reading state
attr HandyDina_WAGO group Smartphones
attr HandyDina_WAGO room IP Überwachung
define act_HandyDina_WAGO notify HandyDina { if ( Value("HandyDina") eq "AKTIV" ) {fhem "set HandyDina_WAGO ".($EVTPART1==1?"on":"off")} }
#----------------------------------------------------------------------------------------------

Der obere Bereich funktioniert auch. Nur hapert es jetzt noch an der Übertragung.

Hatte es auch schon so versucht, auch ohne Erfolg.

define NHandyDina_WAGO notify HandyDina_WAGO { if ( Value("HandyDina") eq "AKTIV" ) {fhem "set HandyDina_WAGO ".($EVTPART1==1?"on":"off");;} }



Was Ich das letzte mal noch schreiben wollte, falls du mal eine kleine Doku zu dem Modbus Modul erstellen wolltest, kann ich dir gerne ein paar Auszüge aus meiner CFG zukommen lassen.  :)

MfG.
Daniel

ChrisD

Hallo,

Du kannst versuchen das notify so zu ändern:
define act_HandyDina_WAGO notify HandyDina { fhem "set HandyDina_WAGO ".($EVTPART0 eq "AKTIV"?"on":"off") }


Die if-Abfrage ist nicht nötig da du bereits auf $EVTPART1 prüfst.

Kurze Erklärung zu meinem Vorschlag:
Bei einem notify auf 'state' steht der Wert in $EVTPART0 da beim Ereignis das Reading weggelassen wird (wieso weiß ich nicht). Im Ausdruck
($EVTPART0 eq "AKTIV"?"on":"off")
prüfe ich auf den vom Ereignis gelieferten Wert, hier also "AKTIV". Da es sich um eine Zeichenkette handelt verwende ich zum Vergleich 'eq' statt '=='.

Ich habe noch immer vor einen Wiki-Eintrag für die Module zu erstellen da der Thread ziemlich unübersichtlich geworden ist. Darin wollte ich einige Beispiele übernehmen. Wenn es soweit ist bin ich dankbar für jede Hilfe.

Grüße,

ChrisD

qwikser

Und wie immer, dickes DANKE!  ;)
Jetzt geht das Licht auch nur noch nach Zeit Programm an wenn ich oder meine Freundin auch wirklich zu Hause sind, super Sache.
Wie gesagt, wenn du paar Beispiele brauchst, einfach fragen.

MfG.
Daniel

oniT

Hallo ChrisD,

ich habe nun auch einmal die ModbusTCPServer, ModbusRegister und ModbusCoil Dateien zum Testen auf den BBB eingespielt. Dabei ist mir folgendes aufgefallen und ich habe eine Frage dazu.

Wenn ich beim Solar-Log über Modbus die Werte abhole, dann scheint dies immer nur möglich zu sein, wenn auch eine Verbindung zum Wechselrichter besteht. Sobald dies nicht mehr der Fall ist kommen disconnects.

2015.01.10 17:41:23 1: 192.168.1.160:502 reappeared (SolarLogServer)
2015.01.10 17:41:23 1: 192.168.1.160:502 disconnected, waiting to reappear (SolarLogServer)


Dies konnte ich bisher auch auf meiner FritzBox festellen. Dort frage ich bisher noch mit der zu Beginn zur Verfügung gestellten 99_UtilsModbus.pm ab. Diese Abfragen mache ich dort mit einem at jede Minute. Bei Sonnenuntergang disable ich dies bis zum Sonnenaufgang. In dieser Zeit erfolgen dann keine Abfragen und entsprechend keine Fehlermeldungen.

In den Attributen von ModbusTCPServer finde ich dort keine Möglichkeit das Öffnen der Verbindung zu unterbrechen. Übersehe ich da etwas? Gibt es eine Möglichkeit? Wenn nicht, würdest Du dies bitte bei Gelegenheit noch einbauen?

Danke

Gruß
Tino
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

ChrisD

Hallo,

Du kannst das Attribut 'dummy' verwenden um die Verbindung zu schließen. Bei Sonnenuntergang z.B.:
attr SolarLogServer dummy 1

Die Meldung
Zitat192.168.1.160:502 reappeared (SolarLogServer)
wird allerdings beim Löschen des Attributes bei Sonnenaufgang weiterhin im Log erschienen da sie nicht vom Modul selbst sondern von DevIO kommt.

Grüße,

ChrisD

oniT

Hallo ChrisD,

ok Danke. Dann setze ich dies auf dummy 1.

Jetzt ist mir ja etwas aufgefallen. Diese Meldung scheint zu kommen, wenn ich mehrere Zugriffe über Modbus auf das selbe Device geöffnet habe. Nun habe ich den Zugriff von der FritzBox disabled und schon sind die Meldungen verschwunden und der Server Status ist OK.

Somit wäre dies Problem scheinbar gelöst.

Jetzt noch zwei Dinge.

1. Da die Abfrage zur Wärmepumpe mit den Dateien aus Deinem git funktioniert, würde ich den Wikieintrag anpassen. Darf ich dort auf Dein git verweisen?

2. Für was steht die erste Zahl, in diesem Fall die 0, vor der Registeradresse?

define radio_volume ModbusRegister 0 12343


Danke

Grüße,
Tino
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

ChrisD

Hallo,

ZitatJetzt ist mir ja etwas aufgefallen. Diese Meldung scheint zu kommen, wenn ich mehrere Zugriffe über Modbus auf das selbe Device geöffnet habe. Nun habe ich den Zugriff von der FritzBox disabled und schon sind die Meldungen verschwunden und der Server Status ist OK.
Dein Server erlaubt wahrscheinlich nur 1 Verbindung, wenn ein 2. sich verbindet wird der 1. getrennt.

Zitat1. Da die Abfrage zur Wärmepumpe mit den Dateien aus Deinem git funktioniert, würde ich den Wikieintrag anpassen. Darf ich dort auf Dein git verweisen?
Ja, gerne.

Zitat2. Für was steht die erste Zahl, in diesem Fall die 0, vor der Registeradresse?
Die Zahl steht bei ModbusTCP für die Unit ID (0-255). Diese erlaubt es z.B. unterschiedliche Teilnehmer die an einem ModbusTCP-Gateway angeschlossen sind anzusprechen. Diese Gateways stellen die Verbindung zwischen einem seriellen Modbus und dem Ethernet her (z.B. Moxa MGate MB3170). Bei vielen 'echten' ModbusTCP-Servern wird die Unit ID ignoriert da sie eigentlich nicht mehr nötig ist. Es gibt aber auch Geräte die eine bestimmte Unit ID voraussetzen damit die Kommunikation möglich ist, meistens 0, 1 oder 255.

Grüße,

ChrisD

oniT

Hallo,

Zitat
Dein Server erlaubt wahrscheinlich nur 1 Verbindung, wenn ein 2. sich verbindet wird der 1. getrennt.
Das habe ich mir auch gedacht. Ich war wohl etwas zu euphorisch, die Meldungen kommen jetzt auch unabhängig ob ich die andere Verbindung geöffnet habe. Mir scheint, als kommt diese wenn ich das Abfrageintervall zu kurz halte. Ich habe im TCPServer sowie bei einem Register gelöscht, so dass die Standardeinstellungen greifen. Im Moment kommt die Meldung opened und der Logeintrag nicht.

Zitat
Ja, gerne.
Ok, danke. Da werde ich bei Gelegenheit einmal den Eintrag anpassen.

Zitat
Die Zahl steht bei ModbusTCP für die Unit ID (0-255).
Ja ok, habe ich mir fast gedacht. Es hätte allerdings auch für den FC stehen können ;-) Habe allerdings eben gelesen, dass man INPUT bzw. HOLDING Register im Attribut einstellen kann.

Gruß,

Tino
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP