How To: Helios KWL Wohnraumbelüftung über Modbus TCP mit fhem

Begonnen von fhem_TS, 28 August 2016, 13:03:52

Vorheriges Thema - Nächstes Thema

fhem_TS

Hallo Forum,

ich war mit einigen hier im Forum in Kontakt um eine Helios KWL EC 370 über Modbus TCP in fhem einzubinden.
Da ich niemanden gefunden hatte der das bisher umgesetzt hier mal mein Weg um das zu realisieren.



Vorbereitung:
Keine; seit dem 26.11.2016 ist die für die Helios benötigte Version der 98_Modbus  durch ein fhem-Update automatisch verfügbar.



Anschließend habe ich folgendes define für die Helios in der fhem.cfg ergänzt:

define Helios_KWL ModbusAttr 180 10 IP.ADRESSE:502 TCP
attr Helios_KWL userattr dev-defShowGet dev-h-defPoll dev-h-read dev-h-write dev-timing-timeout obj-h0-format obj-h0-len obj-h0-poll obj-h0-reading obj-h0-set obj-h1-bswapRegs obj-h1-format obj-h1-len obj-h1-map obj-h1-poll obj-h1-reading obj-h1-set obj-h1-setexpr obj-h1-textArg obj-h1-unpack obj-h180-format obj-h180-len obj-h180-poll obj-h180-reading obj-h180-set sortby verbose
attr Helios_KWL dev-defShowGet 1
attr Helios_KWL dev-h-defPoll 0
attr Helios_KWL dev-h-read 3
attr Helios_KWL dev-h-write 16
attr Helios_KWL dev-timing-timeout 2
attr Helios_KWL group Helios_Status
attr Helios_KWL obj-h1-format %.20s
attr Helios_KWL obj-h1-len 16
attr Helios_KWL obj-h1-poll 0
attr Helios_KWL obj-h1-reading Register
attr Helios_KWL obj-h1-set 1
attr Helios_KWL obj-h1-setexpr ($val."\0")
attr Helios_KWL obj-h1-textArg 1
attr Helios_KWL obj-h1-unpack (a*)
attr Helios_KWL room Helios_KWL
attr Helios_KWL sortby 1


Zudem habe ich für jedes Signal welches ich auslesen möchte einen dummy erstellt (Hier Temperatur der Frischluft):
define KWL_Temp_Frischluft dummy
attr KWL_Temp_Frischluft event-on-change-reading state
attr KWL_Temp_Frischluft group Helios_KWL
attr KWL_Temp_Frischluft room Helios_KWL


Nach einem Neustart sollte die Helios schon als "opened" erkannt werden.
Da die Helios nur ein Register nutzt (Zuerst den Variablennamen hineinschreiben und anschließend den Variablennamen samt aktuellem Wert wieder auslesen) habe ich das Pollen auf 0 gesetzt.
Die Länge steht auf 16 da dies die maximale Länge einer Variable ist die ich auslesen möchte.



Der hier beschriebene Weg funktioniert mit meiner KWL 370 einwandfrei. Es gibt bei anderen Modellen (270/500) Probleme wenn alle Register am Stück gelesen werden sollen.
Die Lösung für dieses Problem hat enno in Post #12 beschrieben[\b]
Anschließend habe ich in der 99_myUtils.pm eine neue Funktion definiert:
sub Fn_KWL_auslesen()
{
{fhem("set Helios_KWL Register v00104")};
my $Frischluft = ReadingsVal("Helios_KWL","Register","-99");
$Frischluft =    (split /=/, $Frischluft , 2 )[1];
$Frischluft =    (split /\0/, $Frischluft )[0];
{fhem("set KWL_Temp_Frischluft $Frischluft")};

# hier können beliebige Signale nach demselben Schema ergänzt werden.

}


Die beiden split-Befehle sind notwendig um im ersten Schritt den Namen vorne abzuschneiden und im zweiten Schritt das angehängte "\0".
Das stört bei der weiteren Verwendung und Steuerung.



Um das ganze nun zyklisch zu bekommen habe ich ein "at" definiert welches die Funktion "Fn_KWL_auslesen()" zyklisch aufruft. In meinem Fall alle 15 Minuten:
define KWL_Update at +*00:15:00 {Fn_KWL_auslesen}
attr KWL_Update room Helios_KWL


Somit füllen sich alle 15 Minuten meine dummy Variablen mit den ausgelesenen Signalen der Helios.

Um die Anlage nun auch steuern zu können benutze ich folgende Befehle in der Kommandozeile:
Modus auf Manuell:
set Helios_KWL Register v00101=1
Stufe auf 3:
set Helios_KWL Register v00102=3

Oder alternativ in der 99_myUtils:
{fhem("set Helios_KWL Register v00101=1")}; # Modus Manuell




An dieser Stelle nochmal herzlichen Dank an StefanStrobel und ChrisD.

Falls noch Fragen sind einfach Fragen.
Codeoptimierungen gegenüber bin ich immer aufgeschlossen  ;)


Grüße
Tobias



Edit 06.12.2016: Verweis auf spezielle Version der 98_Modbus entfernt da integriert in Backup.
Edit 13.12.2016: Verweis auf Ennos Lösung für 270/500 in Post 12.
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB

enno

Nach deiner Anleitung funktioniert es hier auf Cubietruck und KWL sofort.

Ich bekomme nach Setzen der Befehle die Meldung "Timeout reading answer". Die Befehle kommen in der KWL aber an und werden dort auch umgesetzt. Ich bin begeistert. Vielen Dank für die Arbeit.

Gruss
Enno
Einfacher FHEM Anwender auf Intel®NUC mit Proxmox und Debian

MegaData

Mit einer EC 270 geht es leider nicht :( Dachte die sind einigermaßen baugleich... Kann mir jemand helfen die zum laufen zu bekommen... ?

fhem_TS

Hallo MegaData,

bist du mittlerweile weitergekommen? Oder hängst du noch an dem Problem mit "NotNumeric" und nur einem Register wie in dem Thread über Modbus berichtet?

Gruß Tobias
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB

MegaData

Hi Tobias,

nein ich bin leider nicht weiter gekommen :( Ich bekomme immer nur v00000=KWL EC 270W R als Ausgabe. Eine Eingabe nimmt er nicht an: not numeric :( Hast du eine Idee ?

VG,
Chris

fhem_TS

Hallo Chris,

die Meldung "not numeric" deutet für mich darafu hin, dass du entweder nicht die richtige Version der 98_Modbus.pm benutzt (wichtig, nimm die aus dem oben verlinkten Thread, diese wird nach einem fhem Update wahrscheinlich wieder überschrieben worden sein) oder das du TextArg nicht gesetzt hast.

Bitte prüfe nochmal diese beiden Punkte, dann sollte es laufen.

Gruß
Tobias
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB

MegaData

Hi hi !
In der Tat - mit der Version aus dem Thread komme ich schon mal so weit dass ich manuell auslesen und auch schalten kann - super, danke !
Was nicht funktioniert: die Routine um die Dummies zu aktualisieren. Habe in jedem Dummie nur eine 1 drin stehen. Habe natürlich unterschiedliche Variablen verwendet. Die Stufe auszulesen wäre mir noch wichtig :)

VG,
Chris

fhem_TS

Hallo Chris,
sehr gut, der erste Schritt ist gemacht. Kannst du mal ein Log posten um zu sehen welche Antwort du bekommst?

Gruß
Tobias
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB

MegaData

Hi hi !

Okay, nach etwas warten stehen nun in beiden Dummies andere Zahlen, sieht wie die Temperatur aus. Aber es steht halt in beiden das Gleiche drin... Ich hätte jetzt mit den angelegten Dummies zum einem die Lüfterstufe und zum anderen eine Temperatur erwartet. Das Log zeigt das Gleiche was man auch sieht wenn man manuell einen Befehl absetzt: timeout...

2016.11.01 21:05:13.828 3: Helios_KWL: Timeout2 in ReadAnswer for Register
2016.11.01 21:05:13.830 3: set Helios_KWL Register v00104 : Timeout reading answer
2016.11.01 21:05:16.078 3: Helios_KWL: Timeout2 in ReadAnswer for Register
2016.11.01 21:05:16.080 3: set Helios_KWL Register v00102 : Timeout reading answer


Vielleicht ist die Routine da zu schnell und man muss da 2-3 Wartesekunden einbauen ?

VG,
Chris

enno

Hallo Chris,

ich hatte bei der Lösung von Tobias auch das Problem, dass ich nur ein Register lesen konnte. Die Timeout Fehlermeldung habe ich auch im Log. Wenn ich alle Register in einem Rutsch abrufen wollte, bekam ich das Problem, dass Helios wohl nicht schnell genug antwortet.

Um mehrere Register zu lesen habe ich in 99_myUtils.pm fuer jedes Register eine eigene Unterfunktion geschrieben. Diese rufe ich mit einer DOIF Abfrage einzeln auf und warte dazwischen ein paar Sekunden.

([+:15]) (({Fn_KWL_Luefterstufe_auslesen})({Fn_KWL_Abluft_auslesen})({Fn_KWL_Aussenluft_auslesen})({Fn_KWL_Betriebsart_auslesen})({Fn_KWL_Fortluft_auslesen})({Fn_KWL_Zuluft_auslesen})

DOIF Attr wait 0,5,5,5,5,5,5,0

Gruss
Enno
Einfacher FHEM Anwender auf Intel®NUC mit Proxmox und Debian

Daniel

Hallo,

Tobias, danke für deine Beschreibung. Das Auslesen der Außenluft funktioniert einwandfrei!

Enno, kannst du bitte den kompletten Code, den du erweitert hast, posten? Das Aufkopieren der Unterfunktionen in der 99_myUtils.pm ist mir soweit klar... Was muss ich in der fhem.cfg eintragen, damit mehrere Temperaturen ausgelesen and angezeigt werden?

mfg
Daniel 


fhem_TS

Hallo,

also mit meiner KWL 370 läuft das Abarbeiten in einem Rutsch.
@Enno, hast du auch eine 270?
- Falls es bei den 270ern ein Problem mit dem Abarbeiten in einer Funktion gibt ändere ich oben die Anleitung.

@ Daniel
Schau mal in der CommandRef hier : http://fhem.de/commandref_DE.html#DOIF_Relative_Zeitangaben
Dort ist ein Beispiel für ein regelmäßiges DOIF.

Gruß
Tobias
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB

enno

@ Daniel: Code hier weiter unten:
@ Tobias: Ich habe eine Helios KWL EC 500W R mit easyControls v2.21

Hier meine 99_myUtils.pm im Prinzip wie Tobias im ersten Post angegeben, nur in kleine Häppchen unterteilt.

sub Fn_KWL_Aussenluft_auslesen()
{
fhem( "set Helios_KWL Register v00104");
fhem( "get Helios_KWL Register");
my $Aussenluft = ReadingsVal("Helios_KWL","Register","-99");
$Aussenluft = (split /=/, $Aussenluft , 2 )[1];
$Aussenluft = (split /\0/, $Aussenluft )[0];
fhem( "set KWL_Temp_Aussenluft $Aussenluft");
}

sub Fn_KWL_Zuluft_auslesen()
{
fhem( "set Helios_KWL Register v00105");
fhem( "get Helios_KWL Register");
my $Zuluft = ReadingsVal("Helios_KWL","Register","-99");
$Zuluft = (split /=/, $Zuluft , 2 )[1];
$Zuluft = (split /\0/, $Zuluft )[0];
fhem("set KWL_Temp_Zuluft $Zuluft");
}

sub Fn_KWL_Fortluft_auslesen()
{
fhem("set Helios_KWL Register v00106");
fhem( "get Helios_KWL Register");
my $Fortluft = ReadingsVal("Helios_KWL","Register","-99");
$Fortluft = (split /=/, $Fortluft , 2 )[1];
$Fortluft = (split /\0/, $Fortluft )[0];
fhem("set KWL_Temp_Fortluft $Fortluft");
}

sub Fn_KWL_Abluft_auslesen()
{
fhem("set Helios_KWL Register v00107");
fhem( "get Helios_KWL Register");
my $Abluft = ReadingsVal("Helios_KWL","Register","-99");
$Abluft = (split /=/, $Abluft , 2 )[1];
$Abluft = (split /\0/, $Abluft )[0];
fhem("set KWL_Temp_Abluft $Abluft");
}

sub Fn_KWL_Betriebsart_auslesen()
{
fhem("set Helios_KWL Register v00101");
fhem( "get Helios_KWL Register");
my $Betriebsart = ReadingsVal("Helios_KWL","Register","-99");
$Betriebsart = (split /=/, $Betriebsart , 2 )[1];
$Betriebsart = (split /\0/, $Betriebsart )[0];
fhem("set KWL_Temp_Betriebsart $Betriebsart");
}

sub Fn_KWL_Luefterstufe_auslesen()
{
fhem("set Helios_KWL Register v00102");
fhem( "get Helios_KWL Register");
my $Luefterstufe = ReadingsVal("Helios_KWL","Register","-99");
$Luefterstufe = (split /=/, $Luefterstufe , 2 )[1];
$Luefterstufe = (split /\0/, $Luefterstufe )[0];
fhem("set KWL_Temp_Luefterstufe $Luefterstufe");
}


Hier die Dummys die ich mit den Werten fülle:

define KWL_Temp_Aussenluft dummy
attr KWL_Temp_Aussenluft event-on-change-reading state
attr KWL_Temp_Aussenluft room Helios_KWL

define KWL_Temp_Zuluft dummy
attr KWL_Temp_Zuluft event-on-change-reading state
attr KWL_Temp_Zuluft room Helios_KWL

define KWL_Temp_Fortluft dummy
attr KWL_Temp_Fortluft event-on-change-reading state
attr KWL_Temp_Fortluft room Helios_KWL

define KWL_Temp_Abluft dummy
attr KWL_Temp_Abluft event-on-change-reading state
attr KWL_Temp_Abluft room Helios_KWL

define KWL_Temp_Betriebsart dummy
attr KWL_Temp_Betriebsart event-on-change-reading state
attr KWL_Temp_Betriebsart room Helios_KWL

define KWL_Temp_Luefterstufe dummy
attr KWL_Temp_Luefterstufe event-on-change-reading state
attr KWL_Temp_Luefterstufe room Helios_KWL

define KWL_Auslesen_Block dummy
attr KWL_Auslesen_Block event-on-change-reading state
attr KWL_Auslesen_Block room Helios_KWL


und hier die DOIF mit der alle 15 Minuten die aktuellen Werte ausgelesen werden.

define di_KWL_update DOIF ([+:15]) (set KWL_Auslesen_Block on)({Fn_KWL_Luefterstufe_auslesen})({Fn_KWL_Abluft_auslesen})({Fn_KWL_Aussenluft_auslesen})({Fn_KWL_Betriebsart_auslesen})({Fn_KWL_Fortluft_auslesen})({Fn_KWL_Zuluft_auslesen})(set KWL_Auslesen_Block off)
attr di_KWL_update DbLogExclude .*
attr di_KWL_update do always
attr di_KWL_update room Helios_KWL
attr di_KWL_update verbose 0
attr di_KWL_update wait 0,5,5,5,5,5,5,0


Verbose 0, da ich sonst jedesmal den Timeout im Log habe
wait damit die richtigen Register gelesen werden
KWL_Auslesen_Block ist fuer die Steuerung, damit nicht im Moment des Auslesen mit einer anderen Aktion das Auslesen der Register durcheinander bringe. Nutze ich in den anderen DOIF die ich zur Steuerung nutze als Lock.

In der Form funktioniert das bei mir zuverlässig.

Gruss
Enno
Einfacher FHEM Anwender auf Intel®NUC mit Proxmox und Debian

Daniel

@Enno, Tobias: Danke für eure Antworten! Bin begeistert wie gut das geht :) Das Auslesen der KWL270 Daten sind meine ersten Versuche mit FHEM.

fhem_TS

Hallo enno,

was mich noch wundert, nach deinem "set" machst du nochmal ein "get". Das ist bei mir nicht notwendig, soweit ich weiß liest das ModBus Modul das Register nach einem "set" eh nochmal aus.

Kannst du mal prüfen ob deine Funktion ohne das "get" auch noch funktioniert und ob dann die Timeouts weg sind?

In meiner .cfg sieht das so aus:
...
{fhem("set Helios_KWL Register v00105")};
my $Zuluft = ReadingsVal("Helios_KWL","Register","-99");
$Zuluft =    (split /=/, $Zuluft , 2 )[1];
$Zuluft =    (split /\0/, $Zuluft )[0];

{fhem("set Helios_KWL Register v00106")};
my $Fortluft = ReadingsVal("Helios_KWL","Register","-99");
$Fortluft =    (split /=/, $Fortluft , 2 )[1];
$Fortluft =    (split /\0/, $Fortluft )[0];

{fhem("set Helios_KWL Register v00107")};
my $Abluft = ReadingsVal("Helios_KWL","Register","-99");
$Abluft =    (split /=/, $Abluft , 2 )[1];
$Abluft =    (split /\0/, $Abluft )[0];
...



Danke und Gruß
Tobias
fhem@RPi3
FS20 <-> Busware CUL
Homematic <-> HM-USB