KNX Device Definition - Beispiele
Vorwort
Das ist die generelle Seite zum KNX-Modul. Die Command-Referenz ist nach wie vor die aktuellste (und verbindliche) Dokumentation des Moduls. Hier sollen zusätzliche Info's, Tip's & Tricks gegeben werden.
Definition
define <name> KNX <group>:<dpt>[:[gadName]:[set|get|listenonly]:[nosuffix]] [<group>:<dpt> ..] [<group>:<dpt> ..]
Wie in FHEM üblich, alles was hier zwischen <...> dargestellt ist, sind mandatory Angaben! Optionales wird zwischen [...] dargestellt.
Mehrfache <group><dpt>.... sind in einer Definition zulässig. Damit kann man Geräte mit komplexen Funktionen in einem FHEM Gerät abbilden. (siehe Beispiele)
Definitions-Felder im Detail
- group - Das ist die GruppenAdresse (GA) des jeweiligen KNX-Geräts. Diese wird (meist) mit der ETS in das KNX-Gerät programmiert. Ein KNX Aktor reagiert nur auf diese Adresse, wenn es eine seiner eigenen ist. Format: <0-31>/<0-7>/<0-255>
- dpt - Das ist die Definition (Data Point Type), wie FHEM und auch das KNX-Gerät den gesendeten/empfangenen Wert interpretieren! Die Werte (am Bus) können 1bit, 2bit,....4byte lang sein, oder auch 14Char.Text, oder Zeit und Datum. Falls der dpt in FHEM nicht mit dem im KNX-Gerät übereinstimmt, gibts falsche od. gar keine Werte!
- gadName - GruppenAdressName bzw. GA-Alias. Angabe ist optional, sinnvoll ist ein "sprechender Name", z.B. "EinAus" od. "steuern" für eine GA die zum senden eines Befehls dient, oder z.B. "status" für die Rückmeldung vom Gerät. Der gadName beeinflusst auch die entsprechenden Reading-Namen! Ist kein gadName definiert, wird g1...g9 als gadName verwendet.
- set | get | listenonly - alternative optionen, optional, (nur eine Angabe möglich) zur Beeinflussung was FHEM (oder der User) mit dieser Definition machen darf. set bzw get steht für: Fhem darf senden bzw. aktiv ein Gerät abfragen, listenonly bedeutet dass weder was gesendet noch was abgefragt werden darf, es soll nur ankommende Messages verarbeitet werden. Sinnvoll z.B. bei einem Windsensor der in Intervallen die Windgeschwindigkeit auf den Bus sendet.
- nosuffix - optional, beeinflusst den readingNamen. Ohne diesen Parameter lauten Reading-Namen z.b. "EinAus-set" u. "EinAus-get" bzw. "setG1" u. "getG1", mit nosuffix fällt das -set bzw. -get weg, alle gesendeten- und empfangenen-Messages landen im reading EinAus.
Detaillierte Beschreibung: siehe Command-Referenz .
Set Command
Ein Set command ist nur erlaubt, wenn die option im define nicht get oder listenonly ist!
Die Syntax:
set <device> <gadName> <wert>
set <device> <wert>
set <device> g1 <wert>
In der 2ten Zeile fehlt der gadName, das ist dennoch ein gültiges Set, es wird die erste Gruppenadresse (g1) zum senden verwendet.
In der 3ten Zeile wird explizit die erste Gruppenadresse verwendet, allerdings darf dann kein gadName definiert sein!
Get Command
Ein Get command ist nur erlaubt, wenn die option im define nicht set oder listenonly ist! Die Syntax ist analog zum Set command (ohne <wert>). Kommt eine Antwort vom KNX-Gerät wird dieser Wert im entsprechenden Reading gespeichert.
Attribute
Zusätzlich zu den FHEM-standard Attributen sind folgende Attribute verfügbar:
- disable - ident zum FHEM Standard - kein Senden oder Empfangen möglich!
- format - hängt den Inhalt dieses Attr. an den Wert an, - im state Reading! Sinnvoll um z.B. Einheiten hinzuzufügen.
- stateRegex - beeinflusst welcher Wert in das Reading state gesetzt wird, und zwar durch string-substitution. Siehe auch Beispiele.
- stateCmd - beeinflusst welcher Wert in das Reading state gesetzt wird, mittels perl-funktion. Siehe auch Beispiele.
- answerReading - Falls dieses Attr gesetzt ist wird auf einen read-request vom KNX Gerät mit dem Wert von state, oder falls es ein Reading <putName> gibt - mit dessen Wert, geantwortet.
- putCmd - Eine flexiblere Variante von answerReading. Hier kann mittels einer perl Funktion der Rückgabe-Wert bestimmt werden.
- KNX_toggle - Bei einem "toggle-cmd" muss das Device den aktuellen Status des Gerätes wissen. Mit diesem Attr. kann das "Status Device" definiert werden.
- IODev - Auf Grund von Änderungen im IO-Handling durch FHEM (-core) ist dieses Attribut in den allermeisten Fällen nicht mehr nötig und evtl. sogar kontraproduktiv! Die Ausnahme ist: Falls mehrere KNX-IO (TUL,KNXTUL,KNXIO) devices definiert sind. Hier ist jedoch extreme Vorsicht geboten, es kann zu endlosen msg-loops kommen!
Beispiele
Hier soll mit eine Austausch von funktionierenden Beispielen aus dem KNX Bereich stattfinden. Es geht um die Definition, die Darstellung im FHEM-Web und um die Weiterverarbeitung mittels notify, doif, usw.
Viele Anfragen im Forum beziehen sich auf Probleme bei der Definition, Darstellung und "Weiterverarbeitung" von KNX-Geräten. Alle User sind eingeladen, mit weiteren Beispielen mitzuwirken. Im ersten Schritt werden einige Beispiele aus der Command-Referenz hierher übertragen, auch um die Command-Ref (in einem zweiten Schritt) etwas kompakter zu gestalten.
on/off Device - einfach
define Lampe KNX 0/10/11:dpt1
Einfachstes KNX-Device ohne Alias und Rückmeldung.
on/off Device - mit Rückmeldung
define Lampe KNX 0/10/11:dpt1:EinAus 0/10/12:dpt1:Status:listenonly
attr Lampe webCmd EinAus
# attr Lampe webCmd :
attr Lampe stateFormat Status
attr Lampe devStateIcon off:li_wht_off:on on:li_wht_on:off
Hier gibt es 2 GA-Adressen, eine zum Schalten und die 2te für die Rückmeldung vom Aktor (muß natürlich via ETS so programmiert sein!).
Zusätzlich hat jede GA-Adresse nun einen Alias (=gadName), z.B. EinAus, Status. Das Attr "webcmd EinAus" erzeugt ein Pulldown Menü das die jeweilige Funktion ausführt. Falls man kein Pulldown Menü will, nimmt man die 2te Variante von webCmd und klickt auf das DeviceIcon um Ein/Aus zu schalten. DevStateIcon hat den Sinn, damit Icons den Zustand darstellen und beim anklicken die jeweilige Funktion ausführen. Die listenonly Option verhindert, dass ein Set- oder Get-cmd im FHEMWeb dargestellt wird. - Set oder Get sind auf diesen Alias dann nicht möglich!
on/off Device - mit verzögerter Rückmeldung
Es gibt KNX-Aktoren, die erst nach erfolgreicher Ausführung (mit Verzögerung) eine Rückmeldung schicken. Bsp: Großer Drehstrom Motor mit Anlaufstrom-Begrenzung. Nach einem set-cmd (von FHEM) wird vorerst ein hourglass-icon dargestellt, solange bis die Rückmeldung vom KNX-Aktor kommt.
define dpt1_1tst KNX 14/1/1:dpt1:EinAus:set 14/2/1:dpt1:Status:listenonly:nosuffix
attr dpt1_1tst devStateIcon on:general_an:Aus off:general_aus:Ein steuern.*:hourglass:Aus
attr dpt1_1tst stateRegex /EinAus-set/steuern-/ /EinAus-get//
Gleichzeitig ein Beispiel zu stateRegex Verwendung: der 1. Teil muss dem reading[:value] entsprechen, Im konkreten Fall übersetzt das stateRegex "EinAus-set[:value]" nach "steuern-<value> im state-reading, Ein EinAus-get wird ignoriert! Damit kann das state-reading nicht on oder off werden, außer es kommt ein Status von der GA: 14/2/1. Das wird im devStateIcon genutzt, um 3 Zusände darzustellen (on,off,steuern).
Dieses Beispiel könnte auch für die (noch immer) üblichen 1-Taster Garagentor-Steuerungen genutzt werden, In diesem Fall wäre die GA 14/2/1 ein Kontakt, der "Tor zu" ,meldet!
Slider - einfach
define Slider_Test KNX 15/2/2:dpt5:Position
attr Slider_Test webCmd Position
attr Slider_Test widgetOverride Position-set:slider,0,5,100
Slider - mit Rückmeldung
define Slider2_Test KNX 15/2/2:dpt5.001:Position:set:nosuffix 15/2/3:dpt5.001:PosStatus:get:nosuffix
attr Slider2_Test stateCmd { fhem "sleep 0.05 quiet;; setreading $name Position $state" if ($gadName eq 'PosStatus');; return $state;; }
attr Slider2_Test webCmd Position
attr Slider2_Test widgetOverride Position:slider,0,5,100
Das Attr stateCmd setzt den Wert der vom Aktor kommt - zusätzlich in das reading 'Position', damit der Slider immer auch die aktuelle Position anzeigt. Die doppelten semicolons sind aus parsing Gründen nötig. Falls man das Attribut über Device-Detail-view setzt, sind nur einfache ; nötig!
Zwei Slider mit Rückmeldung
Z.B. für eine Jalousie mit Lamellensteuerung. Das ist eine Erweiterung des vorigen Beispiels.
define dpt5test KNX 9/1/1:dpt5.001:blind:set:nosuffix 9/1/2:dpt5.001:blindStatus:listenonly:nosuffix
9/1/3:dpt5.001:slat:set:nosuffix 9/1/4:dpt5.001:slatStatus:listenonly:nosuffix
attr dpt5test devStateIcon {Jal_devStateIcon()}
attr dpt5test room KNXtest
attr dpt5test stateCmd { if ($gadName =~ /(.*)Status/x) {
fhem ("sleep 0.05 quiet; setreading $name $1 $state");
}
return $state;
}
attr dpt5test stateFormat 1:blind
<br/>
2:slat
attr dpt5test webCmd blind:slat
attr dpt5test webCmdLabel Blind
:Slat
attr dpt5test widgetOverride blind:slider,0,1,100 slat:slider,0,10,100
Dazu braucht es noch eine sub in 99_myUtils.pm (siehe auch Beispiel Jalousie / Rolladen). Der Trick liegt in der indizierten Variante von stateFormat (1:blind,...), damit wird auch in devStateIcon dieser Index ausgewertet! Leider gibts für die Lamellen-Stellung nur 3 Icons, für die Stellungen: 0%,50%,100%.
## return string for devStateIcon
## input: none
## return string
sub Jal_devStateIcon {
my $iconstring = 'block.on:fts_door_open@red ' .
"block.off: " .
"aufab.off:black_down:Ab " .
"aufab.on:black_up:Auf " .
'moving:fts_shutter_updown@red:Stop ' .
'1.100.*:fts_shutter_100 1.1\d.*:fts_shutter_10 ' .
'1.2\d.*:fts_shutter_20 1.3\d.*:fts_shutter_30 ' .
'1.4\d.*:fts_shutter_40 1.5\d.*:fts_shutter_50 ' .
'1.6\d.*:fts_shutter_60 1.7\d.*:fts_shutter_70 ' .
'1.8\d.*:fts_shutter_80 1.9\d.*:fts_shutter_90 ' .
'1.\d.*:fts_window_2w ' .
'2.100.*:fts_blade_arc_close_100 ' .
'2.\d\d.*:fts_blade_arc_close_50 ' .
'2.\d.*:fts_blade_arc_close_00 ';
return $iconstring;
}
Zeit und Datum
define timedev KNX 0/0/7:dpt10:time 0/0/8:dpt11:date 0/0/9:dpt19:datetime
Hier sind alle Varianten von Zeit / Datum dargestellt. Die Empfänger müssen den jeweiligen DPT natürlich unterstützen! die entsprechenden set-cmd's lauten:
# setze das Datum auf den Bus:
set timedev date now
set timedev date 01.11.2021
# setze die Zeit auf den Bus:
set timedev time now
set timedev time 18:33:44
# setze Datum und Zeit (gleichzeitig) auf den Bus:
set timedev datetime now
set timedev datetime 01.11.2020_18:33:44
Text senden / empfangen
define textdev KNX 0/0/9:dpt16:txt
Die entsprechenden set-cmd's lauten:
set textdev txt AbCdEfGhIjkLmN # send text to Bus (max 14 Char.)
set textdev txt >CLR< # delete text on the KNX display
Fhem antwortet auf Read Request vom Bus
define putDemo KNX 1/0/30:dpt9.001:temp 1/0/31:dpt9.001:humidity 1/0/32:dpt9:refVal
attr putDemo putCmd {ReadingsNum($name,'refVal-get',0) if ($gadName eq 'temp');}
Es sind 3 GA_Adressen definiert, FHEM antwortet allerdings nur auf einen read-request vom Bus wenn die 1/0/30 Adresse angesprochen wird, mit dem Wert der im refVal reading steht!
Jalousie / Rolladen
Ein komplexes Beispiel, getestet mit einem Jal-Aktor von MDT. Ganz wichtig ist die GA: moving, der Aktor sendet on solange sich die Jalousie bewegt. Das ist ein Parameter, der mittels ETS konfiguriert werden kann. Ergebnis ist ein Device, dass jederzeit die Position anzeigt, Schlaltfllächen für Auf/Ab und einen Slider für's setzen der absoluten Position bietet. Dazu braucht es allerdings 2 sub-routinen in der 99_myUtils!
define Jal_Kueche KNX 5/1/53:dpt1.008:aufab:set:nosuffix
5/1/55:dpt1.010:stop:set:nosuffix
5/1/57:dpt1:moving:listenonly:nosuffix
5/1/58:dpt5.001:position:set:nosuffix
5/1/60:dpt5.001:posstatus:get:nosuffix
5/1/72:dpt1:block:set:nosuffix
5/1/65:dpt1:uppos:listenonly:nosuffix
5/1/66:dpt1:dnpos:listenonly:nosuffix
attr Jal_Kueche cmdIcon Auf:black_up Ab:black_down Stop:remotecontrol/black_btn_RED
attr Jal_Kueche comment GA's: aufab,stop,movestatus,posstatus,Setposition,block,uppos,dnpos
attr Jal_Kueche devStateIcon {Jal_devStateIcon()}
attr Jal_Kueche eventMap { usr=>{"Stop"=>"stop stop","Auf"=>"aufab up","Ab"=>"aufab down"} }
attr Jal_Kueche stateCmd {Jal_stateCmd($name,$gadName,$state)}
attr Jal_Kueche webCmd Auf:Ab:position
attr Jal_Kueche widgetOverride position:slider,0,5,100
.. und die beiden sub's in 99_myUtils.pm (Diese werden von allen Jalousien / Rolladen verwendet.
### Jalousie Utilities
## return string for stateCmd
## input: devicename, Gadname, state
sub Jal_stateCmd {
my ($dname,$gadname,$dstate) = @_;
my $newstate = '';
if (ReadingsVal($dname,"block","off") eq "on" ) {
$newstate = "block:on";
} elsif (ReadingsVal($dname,"moving","off") eq "on" ) {
$newstate = "moving";
Log3 $dname, 5, "in stateCmd-movingon: $dname, $gadname,$dstate,newstate: $newstate";
} else {
$newstate = int((ReadingsNum($dname,"posstatus","0")+5)/10) * 10;
}
return $newstate;
}
## return string for devStateIcon
## input: none
## return string
sub Jal_devStateIcon {
my $iconstring = 'block.on:fts_door_open@red ' .
"block.off: " .
'wind.on:weather_wind@red ' .
'wind.off: ' .
"aufab.off:black_down:Ab " .
"aufab.on:black_up:Auf " .
'moving:fts_shutter_updown@red:Stop ' .
'100.*:fts_shutter_100 1\d.*:fts_shutter_10 ' .
'2\d.*:fts_shutter_20 3\d.*:fts_shutter_30 ' .
'4\d.*:fts_shutter_40 5\d.*:fts_shutter_50 ' .
'6\d.*:fts_shutter_60 7\d.*:fts_shutter_70 ' .
'8\d.*:fts_shutter_80 9\d.*:fts_shutter_90 ' .
'\d.*:fts_window_2w';
return $iconstring;
}
Die sub stateCmd berücksichtigt auch noch die GA: block - z.B. wenn Fenster/Tür offen ist oder einen einen WindAlarm!
Slider - mit Rückmeldung und Wert Umrechnung
Ein komplexer Fall, wo ein Hersteller zwar den dpt5 verwendet, aber sein "eigenes Zahlen-Format" implementiert hat. Konkret geht's um eine Lüftungsanlage, die Stufen 0 (=Aus) bis 8 (=Maximum) verwendet. Am Bus kommen / werden erwartet die folgenden Werte:
0 (Aus)->0, 1->31, 2->63, 3->95, ... , 8->255
Im FHEM-Web sollen aber die Stufen 0-8 verwendet werden.
define KNXStufentest KNX 11/1/18:dpt5:StufeSoll:set:nosuffix 11/1/20:dpt5:StufeIst:get:nosuffix
attr KNXStufentest eventMap { usr => {'Aus' => 'StufeSoll 0', '^Ein' => 'StufeSoll ' . (3 * 32 - 1), '^Stufe (\d)' => '" . sprintf("StufeSoll %d",(($1 == 0)?0:($1 * 32 - 1)) ) . "' },
fw => {'^Ein' => 'Ein', '^Stufe (\d)' => 'Stufe' } }
attr KNXStufentest stateCmd { ($state,undef) = split(/\s/ix,$state);
my $stateC = int(($state + 1) / 32);
if ($gadName eq 'StufeIst') {
fhem ("sleep 0.1;setreading $name Stufe $stateC");
}
if ($gadName eq 'StufeSoll') {
fhem ("sleep 0.1;setreading $name Stufe $stateC");
}
return $state;
}
attr KNXStufentest webCmd Aus:Ein:Stufe
attr KNXStufentest widgetOverride Aus:noArg Ein:noArg Stufe:slider,0,1,8
Ankommende Messages (von Alias StufeIst) werden wie üblich im reading "StufeIst" (Werte: 0-255) gespeichert und zusätzlich umgerechnet und im reading "Stufe" (Wert: 0-8) gespeichert. Ein cmd vom User (Werte: 0-8) wird durch die eventMap umgerechnet und auf den Bus gesendet. Zusätzlich gibt's noch die Schaltflächen "Ein" und "Aus" . Auch diese Werde mittels eventMap auf Stufe 3(=Ein) bzw. Stufe 0(=Aus) umgerechnet. Die Syntax der eventMap ist gewöhnungsbedüftig, aber so funktioniert's! Was noch fehlt ist die Darstellung der Lüfterstufe mittels Icon.
DPT nicht unterstützt im KNX Modul ?
Im KNX-Modul sind (fast) alle DPT's unterstützt, die in den frei verfügbaren Standard-Dokumenten definiert sind. Hersteller definieren manchmal eigene sub-DPT's, die dann möglicherweise nicht unmittelbar unterstützt sind.
Im wesentlichen unterscheiden sich die sub-DPT's z.B. dpt9.020 von den "Haupt-DPT's" z.B. dpt9 durch die angefügte Einheit, den min/max Werte-Bereich, die Skalierung oder einen Offset. Falls also ein Gerät eine 2Byte-float Wert senden will, dann könnte das so aussehen:
define dpt9test KNX 0/4/6:dpt9
attr dpt9test format g/m³ # gramm / m³
und schon steht die richtige Einheit dahinter... Oder Skalierung - Watt -> kW:
attr dpt9test stateCmd { return sprintf("%.3f kW",$state / 1000); }
Falsch definierte DPT's (z.B: dpt5 statt dpt7) produzieren falsche Ergebnisse, sowohl in FHEM als auch im KNX Device!
Übernehmen dieser Beisiele in die eigene config
Die meisten dieser Beispiele sind mittels "exportdevice <name>" erstellt. Bei der Übernahme mit c&p in die FHEM- commandozeile (oder auch Telnet) gibt's Fallstricke...(Es müssen Semicolons u. Zeilenumbrüche maskiert werden). Um das zu umgehen, schlage ich folgenden Vorgangsweise vor:
Definiere z.b. ein (kompliziertes) Attr stateCmd auf der FHEM-cmd Zeile:
attr meinDevice stateCmd {}
... also mit nichts drin! - Damit kann's auch keine syntax-Fehler geben! Danach geht man in den device-detail-View, klickt auf statecmd und mit c&p wird der code zwischen den (äussersten {} ) eingefügt. Selbes Vorgehen gilt auch für komplexe DevstateIcon, notifies, at,... Noch grössere code Teile sind sinnvoller in einer sub-routine in 99_myUtils.pm aufgehoben und werden z.b. im stateCmd aufgerufen:
attr <meinDevice> stateCmd { $state = meineAllerwichtigsteSubroutine(p1,p2,p3); }
Das hat dann auch den Vorteil, dass die sub-Routine von mehreren devices verwendet werden kann!