autocreate: Aufruf der Parse-Routine nach Erzeugen eines neuen EnOcean-Devices

Begonnen von klaus.schauer, 08 Februar 2014, 16:55:36

Vorheriges Thema - Nächstes Thema

klaus.schauer

Für das EnOcean-Modul wäre es sinnvoll, wenn nach dem Anlegen eines neuen Devices durch autocreate unmittelbar die EnOcean Parse-Routine aufgerufen würde und mit den empfangenen Daten versorgt würde. Damit könnten die Inhalte des ersten empfangenen Funktelegramms unmittelbar ausgewertet werden. Dies wäre für ein problemloses teach-in notwendig, z. B. bei den MD15 Heizungsreglern und für das neue UTE teach-in Protokoll. Derzeit ist ein teach-in erst möglich, nachdem das Device in Fhem angelegt wurde, also durch das zweite empfangene Telegramm.

Könnte ein entsprechender Aufruf in autocreate eingebaut werden oder wäre eine andere Lösung vielleicht besser geeignet?

justme1968

ich glaube das wäre auch für andere devices schön wenn das ginge. ich vermute aber das wird nicht ganz einfach das generell zu implementieren weil autocreate völlig asynchron arbeitet.

eine lösung die zwar device spezifisch ist aber jetzt schon funktioniert ist wenn du in der nachricht die das autocreate triggert einfach dir daten mit einem modul internen schlüsselwort einbaust und sie so an sein define durchreichst. da kannst du mit der nachricht dann alles tun was du willst. und vielleicht ist das define sogar die bessere stelle die erste nachricht zu behandeln.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Welche Vor- oder Nachteile hätte es, autocreate aus der Parse-Routine gar nicht aufzurufen sondern das Device in der Parse Routine des Moduls unmittelbar mit allen Attributen und den Eintragungen für das Log-File anzulegen und dann sofort den Inhalt der ersten Nachricht zu verarbeiten?

Gibt es hierfür schon ein Beispiel in einem Modul?
Wie kann man abfragen, falls der Nutzer autocreate deaktiviert hat?

justme1968

es gibt diverse module die autocreate nicht oder nur zum teil verwenden (unter anderem Homematic, OWServer,HUEBridge). ich denke der hautpnachteil ist das man einiges mehrfach implementiert.

eigentlich ist autocreate recht mächtig und schön konfigurierbar. und wenn man anfängt es selber zu implementieren landet man recht schnell dabei alle autocreate attribute abzufragen und noch mal nachzubauen. es fängt ja schon damit an du z.b. log files nur anlegen solltest wenn der benutzer das auch möchte und dann auch noch mit den von ihm gewählten optionen.

ich finde es schöner autocreate zu verwenden so weit es geht. die infrastruktur gibt einiges her.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Dann wäre es doch sinnvoll und hilfreich eine Funktion autocreate() für das Neuanlegen von Devices unmittelbar verfügbar zu machen. Ich finde es auch nicht gut, Einzellösungen nachzubauen, die sicherlich schon besser existieren.

rudolfkoenig

Die Anfangs-Nachricht kann man auswerten, indem man das UNDEFINED Event so konstruiert, dass sie die urspruengliche Nachricht auch enthaelt, und DefineFn so modifiziert, dass nach dem Anlegen des Geraetes diese Daten gleich auswertet. Das habe ich frueher fuer HomeMatic so gebaut, bevor ich das Modul an Martin weitergereicht habe.

P.S.: (etwas off-topic) ein Modul kann die autocreate Parameter selbst setzen, indem es ein AutoCreate Modul-Hash-Eintrag definiert, wie das z.Bsp. FBDECT, FHT, HMS und KS300 das tun.

justme1968

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Das es Lösungen gibt, die ich noch nicht nachvollzogen und verstanden habe, glaube ich. Nur warum ist der Umweg sinnvoller als einfach eine autocreate()-Funktion zur Verfügung zu stellen.

klaus.schauer

Da brauche ich etwas konkretere Hilfe. Ich verstehe das Zusammenspiel der Funktionen nicht.

Wie würde EnOcean_Parse($$) nach dem Sprung zu autocreate erneut mit den vorherigen Übergabeparametern aufgerufen?
In FBDECT fand ich die Routine DoTrigger(). Ist das die Lösung?
Wie müssten die Routinen umgeschrieben werden?


sub
EnOcean_Define($$)
{
  my ($hash, $def) = @_;
  my @a = split("[ \t][ \t]*", $def);
  my $name = $hash->{NAME};
  return "wrong syntax: define <name> EnOcean 8-digit-hex-code"
    if(int(@a) != 3 || $a[2] !~ m/^[A-F0-9]{8}$/i);

  $modules{EnOcean}{defptr}{uc($a[2])} = $hash;
  AssignIoPort($hash);
  # Help FHEMWEB split up devices
  $attr{$name}{subType} = $1 if($name =~ m/EnO_(.*)_$a[2]/);
  $hash->{NOTIFYDEV} = "global";
  return undef;
}

sub
EnOcean_Parse($$)
{
  my ($iohash, $msg) = @_;
  my $ioName = $iohash->{NAME};
  my (undef, $packetType, $rorg, $data, $id, $status, $odata) = split(":", $msg);
  my $rorgname = $EnO_rorgname{$rorg};
  if (!$rorgname) {
    Log3 undef, 2, "EnOcean RORG ($rorg) received from $id unknown.";
    return "";
  }
  my $hash = $modules{EnOcean}{defptr}{$id};
  if (!$hash) {
    Log3 undef, 3, "EnOcean Unknown device with ID $id, please define it";
    return "UNDEFINED EnO_${rorgname}_$id EnOcean $id";
  }
 
[...]

justme1968

alles was nach dem UNDEFINED in der nachricht kommt wird 1:1 ans define durchgereicht. in der JeeLink/LaCrosse version die ich gerade bearbeite gebe ich zum beispiel das iodev das die nachricht empfangen hat mit ans define zurück um dort im AssignIoPort gleich das richtige IODev zu setzen und nicht das zuletzt definierte weil ich mehrere JeeLinks im system haben kann die nicht kompatibel sind:return "UNDEFINED LaCrosse_$rname LaCrosse $raddr [IODev=$hash->{NAME}]"

bei dir könnte das z.b. so aussehen:return "UNDEFINED EnO_${rorgname}_$id EnOcean $id [MSG=$msg]";

damit bekommst du wörtlich ein [MSG=<msg>] im define übergeben das du weiter verarbeiten kannst. die genaue syntax ist dir natürlich selber überlassen. das ganze in ein [] paar einzuschliessen hat meiner meinung nach den vorteil das es ziemlich sicher keinen konflikt mit der bisherigen syntax gibt und durch das verwenden eines eindeutigen zeichens am anfang und am ende das parsen leicht ist auch für den fall das leerzeichen enthalten sind.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Die Lösung scheint grundsätzlich recht einfach zu sein:

sub
EnOcean_Define($$)
{
  my ($hash, $def) = @_;
  my @a = split("[ \t][ \t]*", $def);
  my $name = $hash->{NAME};
  #return "wrong syntax: define <name> EnOcean 8-digit-hex-code"
  #  if(int(@a) != 3 || $a[2] !~ m/^[A-F0-9]{8}$/i);
  ###
  return "wrong syntax: define <name> EnOcean 8-digit-hex-code"
    if(int(@a) < 3 || $a[2] !~ m/^[A-F0-9]{8}$/i);

  $modules{EnOcean}{defptr}{uc($a[2])} = $hash;
  AssignIoPort($hash);
  # Help FHEMWEB split up devices
  $attr{$name}{subType} = $1 if($name =~ m/EnO_(.*)_$a[2]/);
  $hash->{NOTIFYDEV} = "global";
  ###
  if (int(@a) == 4) {
    # parse received device data
    EnOcean_Parse($hash, $a[3]);
  }
  return undef;
}

sub
EnOcean_Parse($$)
{
  my ($iohash, $msg) = @_;
  my (undef, $packetType, $rorg, $data, $id, $status, $odata) = split(":", $msg);
  my $rorgname = $EnO_rorgname{$rorg};
  if (!$rorgname) {
    Log3 undef, 2, "EnOcean RORG ($rorg) received from $id unknown.";
    return "";
  }
  my $hash = $modules{EnOcean}{defptr}{$id};
  if (!$hash) {
    Log3 undef, 3, "EnOcean Unknown device with ID $id, please define it";
    #return "UNDEFINED EnO_${rorgname}_$id EnOcean $id";
    ###
    return "UNDEFINED EnO_${rorgname}_$id EnOcean $id $msg";
  }

[...]

Jetzt wird aber von autocreate die DEF aus der ID und dem folgenden String mit den empfangenen Daten gebildet. Die DEF des log-Eintrages ist dennoch weiterhin in Ordnung.

define EnO_switch_FEFF91C3 EnOcean FEFF91C3 EnOcean:1:F6:70:FEFF91C3:30:01FFFFFFFF5000
attr EnO_switch_FEFF91C3 room EnOcean
attr EnO_switch_FEFF91C3 subType switch
define FileLog_EnO_switch_FEFF91C3 FileLog ./log/EnO_switch_FEFF91C3-%Y.log EnO_switch_FEFF91C3
attr FileLog_EnO_switch_FEFF91C3 logtype text
attr FileLog_EnO_switch_FEFF91C3 room EnOcean

Internals:
   CFGFN     
   DEF        FEFF91C3 EnOcean:1:F6:70:FEFF91C3:30:01FFFFFFFF5000
   IODev      TCM310_0
   LASTInputDev TCM310_0
   MSGCNT     5
   NAME       EnO_switch_FEFF91C3
   NOTIFYDEV  global
   NR         362
   NTFY_ORDER 50-EnO_switch_FEFF91C3
   STATE      B0
   TCM310_0_DestinationID FFFFFFFF
   TCM310_0_MSGCNT 5
   TCM310_0_PacketType 1
   TCM310_0_RSSI -80
   TCM310_0_SecurityLevel 0
   TCM310_0_SubTelNum 1
   TCM310_0_TIME 2014-02-11 21:57:31
   TYPE       EnOcean
   Readings:
     2014-02-11 21:57:31   buttons         released
     2014-02-11 21:57:30   channelB        B0
     2014-02-11 21:57:30   state           B0
Attributes:
   room       EnOcean
   subType    switch

Gibt es da einen Trick? Wo könnte der Fehler liegen?

justme1968

du kannst im define die DEF überschreiben und alles daraus entfernen was nicht drin sein soll. das hatte ich oben vergessen zu schreiben.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Zitat von: justme1968 am 12 Februar 2014, 09:26:20
du kannst im define die DEF überschreiben und alles daraus entfernen was nicht drin sein soll. das hatte ich oben vergessen zu schreiben.
Ok, kann ich machen. Nur warum macht das autocreate nicht gleich richtig?

justme1968

durch autocreate wird das define je mit allen darametern aufgerufen. und das ist was hinterher im DEF steht. fhem weiss ja nicht das $msg nur temporär ist.



gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968