FHEM Forum

FHEM - Hausautomations-Systeme => Homematic => Thema gestartet von: martinp876 am 21 Dezember 2019, 16:34:33

Titel: HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 21 Dezember 2019, 16:34:33
Schon länger trage ich mich mit dem Anliegen, die devices (auch)  über die ccu zu kontrollieren. Ich habe vor etlicher zeit begonnen und dann wieder abgebrochen. Grund ist, dass es für mein verständniss nicht hinreichend generisch implementiert ist.
Was hier kommt ist natürlich meine private Ansicht, welche ich definitiv auf die eine oder andere Art verfolgen werde. Was ich sagen will: es sind vorschläge und konstruktive (keine negative) Kritik. Sollte es auf Ablehnung stossen, kein Problem. Dann mache ich privat weiter.
Also:
Ich werde immer den channel Ansatz für entities nutzen. Diesen brauche ich zwingend generisch. Wenn ich kanal 3 eines aktors ansehe darf keines der readings mit 3.LEVEL beginnen. Es ist schlicht level... usw.
Im kanal haben die device infos nichts verloren. Hierzu habe ich device 0.
Die capital letter sind störend. Nicht so prickelnd, nicht fhem üblich. Sollte man einfach umstezen.
Ich habe einmal einen dimmer probiert. Man kann ihn über pct dimmen. Allerdings fehlt das reading, was den slider dann nicht bedient. Geht natürlich nur über das entfernen der kanalnummer in den readings namen.

Beim dimmer fehlen einige Kommandos wie on\off. Das übliche eben.

Ich bin erst am Anfang....  Gibt es einen einfachen Weg, die konfig so zu implementieren, wie ich es dargestellt habe? Ich habe nicht vor, jedes reading manuell umzubenennen.

In jeden Fall, vielen dank für das Modul.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 21 Dezember 2019, 17:22:32
Ich nehme an, du meinst HMCCUCHN.

Alle Deine Wünsche lassen sich mit Attributen umsetzen, außer die Kanalnummer im Readingname. Das müsste ich noch konfigurierbar machen.

Die  Readings in Kleinbuchstaben gibts mit ccureadingformat = datapointlc, lc am Ende für lowercase.

Ein pct Reading bekommst du mit

ccureadingname LEVEL:+pct, ohne das + wird LEVEL durch pct ersetzt.

Den Kanal 0 kannst du mit ccuflags = nochn0 abschalten. Finde ich aber ganz praktisch, da hier die Lowbat und Unreach States drin stecken
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 22 Dezember 2019, 11:30:12
ok, danke. Ich komme schon einmal weiter.
Ich haben also
ccureadingformat = datapointlc
gesetzt. lc ist klar, danke.
Du hast alles einstellbar gemacht. Gibt jede menge optionen - und viel Arbeit sich durchzuwurschteln.
zu ccureadingformat  sehe ich ccudef-readingfilter. Das hört sich dann schon viel besser an. Ich könnte wenn notwendig, aber will nur "unter Zwang" solche Attribute bei jeder Entity setzen.
Dein Vorschlag für mich ist also präzise
set  ccu ccudef-readingformat datapointlc
Wobei ich in der Beschreibung "commandref" den Hinweis vermissem dass dieses Attribut nicht am Device sondern der CCU anzubringen ist.
Unsauber: Das Attribut funktioniert nur für "neue" Readings. Beim Umschalten sollten m.E. alle bestehenden Readings umgearbeitet werden. Das macht Arbeit, klar. Aber wenn du es nicht machst muss es der User jedes mal machen.
Gleiches gilt für ccuflags = nochn0.
Hierzu ist mir das Verhalten noch unklar - ich kann es im Code sucher oder experimintieren. Ist aber langwierig - Beschreibung wäre cool:
a) setze ich ccuflags = nochn0 in der ccu - wirkt dies auf alle Entities der ccu?
b) wenn ich das Attribut überall setze - was passiert mit Kanal 0? Sind dann alle Readings weg? Hoffentlich nicht.

Ich finde es unpraktisch eine Liste von Readings des Device im kanal zu haben. Eine Zusammenfassung ist sicher ok. Z.B. Message State: Commands pending/done/fault sowie DeviceHealth:ok/batlow/reachabel/overheat. 2 Readings -ok. RSSI zu Peers - no!

Aber neben der (konstruktiven!) Kritik - ich sehe das Modul grundsätzlich natürlich positiv. Vielen Dank hierfür.

Jetzt muss ich erst einmal suchen, was get config macht und warum bei mir "Cannot detect or create external RPC device" erscheint. Und ob das irgendwo beschrieben ist.

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 22 Dezember 2019, 14:28:41
Ich habe nun etwas ccureadingname gespielt. Ziel ist es, den level des dimmers darzustellen. Für fhem brauche ich
level und pct als reading. Weiter level_real natürlich für hm dimmer.
Etwas inkonsistent ist:
- nutze ich +pct wird ein zusätzliches reading ohne nummer (1.)  eingefügt. Jetzt: level oder level_real?
- nutze ich pct werden die beiden readings 1.xxx ersetzt. Die alten muss ich (natürlich und leider) manuell löschen
Ok, wenn ich es korrekt sehe wird eine regular expression genutzt wobei die Kanal nummer (leider) teil des readings ist.
Im kommandref beschrieben ist, dass bei mehrfachtreffern nur ein reading erzeugt wird. Der inhalt ist mir nicht wirklich klar.

De-facto brauche ich als anwender nun eine übersetzungstabelle. Und zwar devicetyp\channel(typ)\ccureading nach fhem reading.
Ich will das schliesslich nicht für jede entity eintragen. Alle entities gleichen typs müssen identische readings nutzen.
Daraus müssen dann die attribute generiert und gesetzt werden.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 23 Dezember 2019, 09:54:00
meine Probleme:
Scheinbar brauche ich irgendwie einen externen RPC server. Hierzu kommen immer fehlermeldungen, aber ich finde keinen Info in Wiki wie  best-current practice o.ä.
Mache ich das Grundsätzlich falsch?

get <chan> config <device>
a) was soll ich als "device" angeben?
   Es muss ein HMCCU I/O Device existieren. Was ist ein HMCCU I/O Device? Ich habe eine HMccu definiert. Das reicht nicht.
b) warum muss ich das Device überhaupt angeben? Kann man das nicht automatisch einsetzen?

get <chan> configdesc  <device>
a) das Kommando hat keinen Parameter. Doku und Implementierung sind nicht konsistent
b) Es funktioniert bei mir nicht, mangels external RPC device.  Brauche ich das  udn wie bekomme ich es?
get <chan> configdesc  <device>

Scheinbar habe ich ein grundsätzliches Problem mit einem external RPC device

get <chan> datapoint <datapoint>
liefert kein Ergebnis - keine Reaktion. Wird das Reading upgedated? Sollet ein Fenster aufgehen?

attr <chan> statedatapoint <datapoint>
a) <datapoint> ist der CCU-datapoint, nicht der Umgesetzt. Ist m.E. schade - sollte aber zumindest beschrieben werden. Allerdings ist mir nicht klar, warum ich das brauche. FHEM bietet für State bereits default attribut. Warum nutzt man nicht diese? Was macht statedatapoint anders?

Zitatget <chan> devstate
was macht dies? Es ist ein Update readings für genau einen Parameter. macht 'update' nicht das gleich? Ist das Kommando überflüssig?

Zitatget <chan> update ...
Die Beschreibung verstehe ich nicht
a) er werden ALLE Datapoints upgedated (sehr gut). Das sollte idR automatisch gehen. Ist also einfach ein manueller Trigger in Sonderfällen. korrekt?
b) With option 'State' the device is queried. Was sagt mir das? Wo soll das Device hin? Ist es ein Device oder der Channel, also schlicht die Entity? Und was wird dann upgedatet - immer noch alle Datapoints?
c)This request method is more accurate but slower then 'Value'.Das ist nun beängstigend. Was bedeutet, dass "Value" nicht akkurat ist? Es kommen manchmal falsche Werte? Ich verstehe den Unterschied schlicht nicht.

In den Beschreibungen wäre es m.E. korrekt zwischen Kanälen und Devices zu unterscheiden. Die Begriffe werden vermischt. Ich nutze (hoffentlich immer :) ) Kanäle, Devices dediziert und entites wenn beides möglich ist.

In der Doku zu HMccu device.list fehlen m.E. ein paar umbrüche für die Lesbarkeit. Mein Vorschlag:

      <li><b>get &lt;name&gt; devicelist create &lt;devexp&gt; [t={chn|<u>dev</u>|all}]
      [p=&lt;prefix&gt;] [s=&lt;suffix&gt;] [f=&lt;format&gt;] [defattr] [duplicates]
      [save] [&lt;attr&gt;=&lt;value&gt; [...]]</b><br/>
         create: HMCCU will automatically create client entities for all CCU entities
         matching specified regular expression in devexp. <br>
         t=chn/dev/all: Creation of entities is limited to CCU channels or devices. dev = default. <br>
         prefix/suffix/format: defines a template for entity names in FHEM. All can contain format identifiers which are substituted by corresponding values of the CCU device or
         channel: <br>
         <li>
         %n = CCU object name (channel or device)<br>
         %d = CCU device name<br>
         %a = CCU address<br>
         </li>
         Additionally a list of default attributes for the created entities can be specified.<br>
         defattr: HMCCU sets default attributes for entities if available. <br>
         duplicates: HMCCU will not only create non-existing entites but also overwrite existing entities for existing addresses. <br>
         save: auto-save FHEM config after finishing
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 23 Dezember 2019, 13:44:37
RPC Devices / Server

Das RPC Device (HMCCURPCPROC) wird für alle Funktionen benötigt, die die RPC Schnittstellen der CCU benötigen:


Das ist im Wiki-Hauptartikel zu HMcCU beschrieben (Stichwort RPC Server konfigurieren).

Die anderen Befehle wie get/set datapoint oder auch get update benutzen die ReGA Schnittstelle der CCU, kommen also ohne RPC Device aus.
Es genügt, im IO Device das Attribut ccuinterfaces auf die verwendeten Schnittstellen zu setzten, dann werden die RPC Devices beim ersten Starten der RPC Server automatisch angelegt.

Die Architektur entspricht im Prinzip der Umsetzung der CCU Schnittstellen in ioBroker, OpenHab, ...

1 IO Device je CCU
1 RPC Device je CCU Schnittstelle (hmip, bidcos, wired, ...)
>= 1 Device je Gerät oder Kanal

Readingformate

Die Readings umzubauen, sobald sich an einem der Attribute etwas ändert (z.B. Format des Readingnames) ist ein ziemlicher Aufwand. Aktuell könnte ein Nutzer vor oder nach der Änderung der Attribute einmal die alten Readings mit set clear löschen und dann per get update einmal alle neu von der CCU holen. Oder er wartet, bis sie über den RPC Server automatisch nach und nach aktualisiert werden. Kurzfristig könnte ich die beiden Schritte automatisieren, d.h. eine Änderung der Attribute hat ein set clear / get update zur Folge.

Das Attribut ccuscaleval sorgt für die Skalierung von Werten wie z.B. LEVEL, mach also aus 0..1 0..100. Leider ist es derzeit noch nicht möglich, beides zu haben. Also z.B. in LEVEL die Werte 0..1 und in pct die Werte 0..100.

get / set config

Die Syntax ist abhängig davon, ob man ein HMCCUCHN oder HMCCUDEV Device verwendet. Bei HMCCUCHN bewirkt get <name> config das Auslesen der Parameter von dem Kanal, auf den sich das HMCCUCHN Device bezieht. Wenn dieser Kanal keine konfigurierbaren Parameter besitzt, schlägt der Befehl fehlt.
'device' ist kein Platzhalter sondern tatsächlich der String "device". Wenn Du diese Option bei einem HMCCUCHN Device anhängst, werden die Konfigurationsparameter vom Gerät (nicht die vom Kanal) ausgelesen. Meistens sind Parameter wie AES gerätebezogen. Ich weiß, das ist wieder ein Stück weit inkonsequent, da von einem Kanaldevice auf Geräteparameter zugegriffen werden kann. Macht aber das Leben manchmal einfacher und erspart ein separates HMCCUDEV Device.

Zitat
get <chan> datapoint <datapoint>
liefert kein Ergebnis - keine Reaktion. Wird das Reading upgedated? Sollet ein Fenster aufgehen?
Das entsprechende Reading sollte aktualisiert werden. Zu beachten: Der Datenpunkt muss im regulären Ausdruck vom Attribut ccureadingfilter enthalten sein.

Zitat
attr <chan> statedatapoint <datapoint>
a) <datapoint> ist der CCU-datapoint, nicht der Umgesetzt. Ist m.E. schade - sollte aber zumindest beschrieben werden. Allerdings ist mir nicht klar, warum ich das brauche. FHEM bietet für State bereits default attribut. Warum nutzt man nicht diese? Was macht statedatapoint anders?
Legt den Datenpunkt fest, dessen Wert in state/STATE geschrieben wird. Dieser Datenpunkt wird auch angesprochen, wenn Du zusätzlich mit statevals Werte für den statedatapoint festgelegt hast. Beispiel:
[/list]
attr <name> statevals on:1,off:0
attr <name> statedatapoint 2.STATE
set <name> on

Außerdem fließt statedatapoint noch in andere Funktionen ein, ist also relativ wichtig.

Zitat
get <chan> devstate
was macht dies? Es ist ein Update readings für genau einen Parameter. macht 'update' nicht das gleich? Ist das Kommando überflüssig?
Ja, ist eigentlich veraltet. Bezieht sich immer auf den Datenpunkt, der als statedatapoint festgelegt wurde.

Zitat
get <chan> update ...
Die Beschreibung verstehe ich nicht
a) er werden ALLE Datapoints upgedated (sehr gut). Das sollte idR automatisch gehen. Ist also einfach ein manueller Trigger in Sonderfällen. korrekt?
RPC Devices sind Dein Freund. Jedes RPC Device startet einen RPC-Server, der Reading-Aktualisierungen von der CCU empfängt und alle entsprechenden Devices (HMCCUCHN, HMCCUDEV) aktualisiert. Ohne RPC Device funktioniert nur ein Bruchteil. Daher siehe auch HMCCU Wiki Konfiguration des RPC Servers.

Zitat
b) With option 'State' the device is queried. Was sagt mir das? Wo soll das Device hin? Ist es ein Device oder der Channel, also schlicht die Entity? Und was wird dann upgedatet - immer noch alle Datapoints?
c)This request method is more accurate but slower then 'Value'.Das ist nun beängstigend. Was bedeutet, dass "Value" nicht akkurat ist? Es kommen manchmal falsche Werte? Ich verstehe den Unterschied schlicht nicht.

Die ReGa Schnittstelle der CCU bietet zwei Methoden, auf den Wert eines Datenpunktes zuzugreifen. Mit VALUE() bekommt man den Wert, den ein Datenpunkt aktuell in der CCU hat. Dieser ist ggf. einige Sekunden oder Minuten alt.
Mit STATE() hingegen fragt die CCU explizit immer beim Gerät nach dem tatsächlichen Wert eines Datenpunktes. Dieser zusätzliche Kommunikationsschritt kostet Zeit und wirkt sich auf den Duty Cycle aus.

HMCCUCHN -- VALUE() --> CCU
HMCCUCHN -- STATE() --> CCU --> Gerät

Sofern man die RPC Devices nutzt, gibt es nur wenig Gründe, per get datapoint oder get update Werte direkt von der CCU zu holen.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 23 Dezember 2019, 17:43:14
Hi, ich komme langsam voran. Ich befasse mich erst einmal aussschliesslich mit get kommandos und Darstellung da ich an meinem livesystem arbeite :)

klar kenne ich das Problem mit historschen Gegebenheiten... ;)

Das mit "Device" habe ich nun endlich auch gemerkt - danke.

Zum Kommando conficdesc: Mein Vorschlag ist in Zeile 7175 folgender Code
elsif ($method eq 'getParamsetDescription') {
my @operFlags = ('', 'R', 'W', 'RW', 'E', 'RE', 'WE', 'RWE');
foreach my $key (sort keys %$reqResult) {
$result .= $key.": "
                      ."\t["      .$operFlags[$reqResult->{$key}->{OPERATIONS}]."]"
                      ."\ttyp: "  .$reqResult->{$key}->{TYPE}
                      ."\trange: ".$reqResult->{$key}->{MIN}
                      ." - "      .$reqResult->{$key}->{MAX}
                      .(defined $reqResult->{$key}{VALUE_LIST}
                                ?"\n                 ".join("\n                 ",@{$reqResult->{$key}{VALUE_LIST}})
                                :"\tunit: " .$reqResult->{$key}->{UNIT})
                      ."\n"
                      ;
}
}


Das ist hier der erste Teil, da die Link kommandos noch fehlen.
Die Enums muss man permanent speichern um sie in allen Darstellungen einsetzen zu können.
Eigentlich ist das beim Booten durchzuziehen. Oder nach Bedarf bei der Anzeige...
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 23 Dezember 2019, 18:03:44
und 88_HMCCUCHN.pm zeile 573:
elsif ($opt eq 'configdesc') {
my $ccuobj = $ccuaddr;
my $par = shift @$a;
if (defined ($par) && $par eq 'device') {
($ccuobj, undef) = HMCCU_SplitChnAddr ($ccuaddr);
}

my ($rc1, $result1) = HMCCU_RPCRequest ($hash, "getParamsetDescription", $ccuobj, "MASTER", undef);
return HMCCU_SetError ($hash, $rc1, $result1) if ($rc1 < 0);
my ($rc2, $result2) = HMCCU_RPCRequest ($hash, "getParamsetDescription", $ccuobj, "LINK", undef);
return HMCCU_SetError ($hash, $rc2, $result2) if ($rc2 < 0);
return "MASTER:\n".$result1."LINK:\n".$result2;
}


Dann haben wir erst einmal (für Channel ;) ) die formale Beschreibung der Register abfragbar. Incl Grenzwerte und enums.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 24 Dezember 2019, 09:48:57
so, und noch "ENUMs" die Dritte - habe einmal darüber geschlafen ;). Hier meine Herleitung:

- Sollen enums implementiert werden? => es gibt keine Alternative- ein Muss
- Welche enums? => alle. Es gibt welche für config und datapoints, values, links, master
- wie wird es implementiert?
  a) dynamisch abfragen, also bei Jeder nutzung die CCU befragen => lehne ich ab
  b) statisch speichern. Praktikabel ist, einen hash anzulegen welcher sukzesive befüllt wird. Nach jedem neustart. Für Maintenance können man ein kommando zum "neulesen" einführen. Das dauert aber noch
- Wo ist es zu speichern
  Es wird bei der Visualisierung benötigt, also in HMCCUCHN (DEV auch, ignoriere ich aber ;) ). Gefüllt wird es bei Instanziieren der Entity. Hier sollten alle fehlenden Enums gelesen werden.
  => ein Hash welcher global angelegt wird ist wohl notwendig. Angelegt sollte er von HMCCU werden. Genutzt von HMCCUCHN/DEV und gefüllt von RPC
- Nur enums? Wohl nicht. Das ist zu kurz gesprungen und wird uns irgendwann auf die Füsse fallen. Also gleich die "Description" speichern.
- Struktur des Hash
  * Im Prinzip wird es aussehen wie die Register in HMConfig. Ist ja auch das gleiche. Am Ende des Tages kannst du das gesamte Konzekt der Entity "Beschreibung" so aufsetzen. Deutlicher Vorteil zu HMConfig: Du kannst die Daten automatisch aus der CCU befüllen lassen
- Lebensdauer: Die Beschreibungsdaten ändern sich nur nach einem Update der CCU. Erweitert werden sie ggf. wenn ein neuer Typ von Device instanziiert wird. Dann sind dessen Daten aus der CCU abzufragen. => erst einmal reicht es, nach Neustart bei NULL anzufangen und bei jeden Define prüfen, ob das Device schon geladen ist.

Ich mache mir noch ein paar Gedanken

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 25 Dezember 2019, 12:58:13
Ich habe mittlerweile einige Deiner Anforderungen umgesetzt und im Test.

Das mit den enums verstehe ich nicht. Ja, es gibt sehr viele davon in der CCU, sowohl auf RPC- als auch auf Logikschicht-Ebene. Wozu werden die in FHEM benötigt? Hast Du ein Beispiel?

Der Befehl RPC Request "getParamsetDescription" und damit der Befehl get configdesc funktioniert nicht für jeden Gerätetyp. Von daher kann man sich nicht darauf verlassen. Manchmal liefert er auch falsche oder unvollständige Informationen. Daher habe ich diesen Befehl nur als Info implementiert, die helfen kann, die Bedeutung der Config-Parameter zu entschlüsseln, da diese bei EQ-3 leider nicht dokumentiert sind.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 26 Dezember 2019, 16:02:30
Ich habe einmal etwas experimentiert - verstehe langsam besser, was schon implemenitert ist und was ich zumindest noch nicht gefunden haben.
Ideen und Vorstellungen habe ich viele. Sicher nicht alle sinnvoll :( . Aber wichtig hierbei ist,  das Konzept  und die gewünschte Architektur zu verstehen. Wäre einfach, wenn man sich ein Wochenende für das Diskussionen zeit nehmen würde.

Enums:
Mir nicht klar, was dir nicht klar ist ;).
1) enums sind m.E. wichtig, da es der für mich einzige Weg der Programmierung ist. So will ich die Werte (enums) für Register (und eigentich alles) aus der CCU sehen. So haben bspw die folgenden Register die angegebenen Namen als Werte. Genau diese will ich nutzen - zum Lesen und zun Schreiben
SHORT_ON_TIME_MODE:VALUE_LIST=ARRAY    ABSOLUTE,MINIMAL
SHORT_JT_REFON:VALUE_LISTNO_JUMP_IGNORE_COMMAND,ONDELAY,REFON,RAMPON,ON,OFFDELAY,REFOFF,RAMPOFF,OFF
2)Die Enums müssen zur Nutzung geholt oder gespeichert werden. Natürlich müssen sie immer erst einmal geholt (aus der CCU) werden. Das sollte man nur einmal machen. Dann in FHEM speichern und nutzen. Alles andere ist eine Performance-Kathastrophe aus meiner Sicht.
3) Nutzung der Enums für Register ist a) im Kommando, die Register-beschreibung auszugeben und b) die Registerwerte. In CUL_HM vergleichbar den Kommandos get regList und get regTable
4) neben den enums sind natürlich auch die anderen Beschreibungen der Register in regList auszugeben. Also min/max wert, und Einheit. Genauso wie Lese und Schreibbarkeit.

5) enums sind natürlich nicht auf Register beschränkt. Diese sind für alle Kommandos notwendig. Hier sind die "VALUES" tabellen interessant.

Du hast sicher meine Codebeispiele gesehen. Allerdings würde ich den Code wegen der von mir präferierten architekturänderungen so auf dauer nicht implementieren. Aktuell könntest du es einfach einbauen.

ZitatDer Befehl RPC Request "getParamsetDescription" und damit der Befehl get configdesc funktioniert nicht für jeden Gerätetyp.
Kann ich mir nicht vorstellen. Möglich, dass es keine Werte gibt. Kannst du mir 2-3 Beispiele nennen? Also die Modelle. Dann werde ich es prüfen. Die CCU arbeitet mit diesen Werten - bei Fehlern wüde ich für Fehlinterpretationen unserer Seits vermuten.
Die Bedeutung der Parameter ist in CUL_HM weitgehend dekodiert. Wo sind deine Probleme? Bisher kann ich es recht gut lesen.

==> Ich muss die Datenarchitektur deiner Module verstehen.

Übrigens: Die Aufteilung HMCCU und HMCCUCHN hätte ich mir bei CUL_HM auch gewünscht. Das ist super, hatte mich nie getraut, es umzustellen. Ich habe hmInfo als kleinen Ersatz. Einige der zentralen Funktionen hätte ich auch gerne in HMCCU
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 27 Dezember 2019, 08:43:27
Vielleicht habe ich dich aber nicht korrekt verstanden bezüglich der enum Frage. Noch ein paar Gedanken
Für die Beschreibung der Devices und Funktionalitäten würde ich ein ( oder mehrere) hashes anlegen, welche von HMCCU befüllt werden und von HMCCUCHN genutzt werden. HMCCUDEV wenn du es willst -interessiert mich nicht.

Wenn HMCCUCHN definiert wird muss geprüft werden
? ist die Seriennummer schon instanziiert (hier ist es ja nur ein kanal). 
    => nein : führe "getDeviceDescription" aus.


Hier bekomme ich die Info, welche  wie folgt abzulegen ist
  - DevDef{HM-LC-Dim1TPBU-FM}{AVAILABLE_FIRMWARE}=2.9
     DevDef{HM-LC-Dim1TPBU-FM}{UPDATABLE}=1
     DevDef{HM-LC-Dim1TPBU-FM}{RX_MODE}=1
     DevDef{HM-LC-Dim1TPBU-FM}{FLAGS}=1
     DevDef{HM-LC-Dim1TPBU-FM}{PARAMSETS}=("MASTER")
     
     DevDef{HM-LC-Dim1TPBU-FM}{CHILDREN}{CNT}=4                            # count of children incl MAINTENANCE channel
     DevDef{HM-LC-Dim1TPBU-FM}{CHILDREN}{DEF}{0}{TYPE}="MAINTENANCE"       # definition of channel 0 MEINTENANCE
     DevDef{HM-LC-Dim1TPBU-FM}{CHILDREN}{DEF}{1}{TYPE}="DIMMER"       # definition of channel 1   
     DevDef{HM-LC-Dim1TPBU-FM}{CHILDREN}{DEF}{2}{TYPE}="VIRTUAL_DIMMER"       # definition of channel 2
     DevDef{HM-LC-Dim1TPBU-FM}{CHILDREN}{DEF}{3}{TYPE}="VIRTUAL_DIMMER"       # definition of channel 2

     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{MAINTENANCE}{PARAMSETS}=("MASTER","VALUES")   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{MAINTENANCE}{DIRECTION}=0   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{MAINTENANCE}{FLAGS}=3     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{MAINTENANCE}{LINK_SOURCE_ROLES}=""     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{MAINTENANCE}{LINK_TARGET_ROLES}=""     

     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{DIMMER}{PARAMSETS}=("MASTER","VALUES","LINK")   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{DIMMER}{DIRECTION}=2   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{DIMMER}{FLAGS}=1     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{DIMMER}{LINK_SOURCE_ROLES}=""     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{DIMMER}{LINK_TARGET_ROLES}="SWITCH WCS_TIPTRONIC_SENSOR WEATHER_CS"     
     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{VIRTUAL_DIMMER}{PARAMSETS}=("MASTER","VALUES","LINK")   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{VIRTUAL_DIMMER}{DIRECTION}=2   
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{VIRTUAL_DIMMER}{FLAGS}=1     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{VIRTUAL_DIMMER}{LINK_SOURCE_ROLES}=""     
     DevDef{HM-LC-Dim1TPBU-FM}{ChDef}{VIRTUAL_DIMMER}{LINK_TARGET_ROLES}="SWITCH WCS_TIPTRONIC_SENSOR WEATHER_CS"     


Das Dynamische Hash ist dann jeder Entity entsprechend zuzuordnen und tyisch in "helper" anzulegen
    $def{entityname}{helper}{defInfo}{AES_ACTIVE}=[0/1]
   
    Und im Kanal 0 kommt die Device Information zum Tragen:
    $def{entityname}{helper}{defInfo}{dev}{ADDRESS}="IEQ0545891"
    $def{entityname}{helper}{defInfo}{dev}{FIRMWARE}="2.1"
    $def{entityname}{helper}{defInfo}{dev}{INTERFACE}="KEQ1038237"
    $def{entityname}{helper}{defInfo}{dev}{RF_ADDRESS}="1617137"
   

Wenn du also die erste Entity des Models HM-LC-Dim1TPBU-FM instanziierst wird der Hash gefüllt. Beim 2. Mal ist das erledigt, die Daten sind unveränderlich.
Leider sehe ich keine Zusammenfassung, so dass mehrere Models den selben Hash nutzen könnten. Wäre möglich, gibt eq3 nicht her.
Danach sind die ParameterSetDescriptions zu holen und zu cachen. Auch diese sind unveränderlich.

Danach werden die getParamsetDescription ausgewertet. Beim Erstellen des obigen Hash (also wenn er noch nicht existiert) werden die Parameter Beschreibungen gelesen. MASTER und LINK beschreiben Register, werden also im selben Hash gespeichert
bspw

{reg}{SHORT_ON_TIME_MODE}{DEFAULT}=0
  {reg}{SHORT_ON_TIME_MODE}{FLAGS}=1
  {reg}{SHORT_ON_TIME_MODE}{MAX}=1
  {reg}{SHORT_ON_TIME_MODE}{MIN}=0
  {reg}{SHORT_ON_TIME_MODE}{OPERATIONS}=3
  {reg}{SHORT_ON_TIME_MODE}{TAB_ORDER}=15
  {reg}{SHORT_ON_TIME_MODE}{TYPE}=ENUM
  {reg}{SHORT_ON_TIME_MODE}{UNIT}=""
  {reg}{SHORT_ON_TIME_MODE}{VALUE_LIST}=("ABSOLUTE","MINIMAL")



bei VALUES ... kann man eigentlich identisch verfahren und es im gleichen Hash ablegen.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 27 Dezember 2019, 16:53:31
Ok, hab's verstanden. HMCCU legt bereits jetzt eine ganze Menge Infos unter

$hash->{hmccu}

ab. Auch Gerätetyp spezifische Infos. Diese Struktur wäre dann um die enums und weitere Infos zu ergänzen. Das Konzept, wie diese Daten ermittelt werden, folgt aber einem komplett anderen Ansatz. Ein Großteil der Infos wird von einem (einzigen) Homematic Script abgefragt. Gegenüber der von Dir vorgeschlagenen RPC Methode hat das den großen Vorteil, dass alle Infos mit einem einzigen Http Request abgefragt werden können. Bei der RPC Methode brauche ich je Device mindestens 4 Request (getParamsetDesc für MASTER, VALUE und LINK + getDeviceDesc). Da wird zumindest die CCU2 ziemlich schnell ziemlich dicke Backen machen. Je Device, weil sich die paramsets je nach Firmwarestand eines Geräts unterscheiden können.

Einige Infos gibt es gar nicht auf RPC Ebene. Die müsste ich noch zusätzlich per HM Script holen. Ich kann das mal testen mit meiner CCU3. Wenn es da schon zu Timeouts kommt, funktioniert es auf der CCU2 sowieso nicht.

Einige CCU Erweiterungen wie HUE, HVL etc. bieten nicht mal RPC Schnittstellen an. Oder sie implementieren Methoden wie getParamsetDesc nicht (CuXD sowei ich weiß). Wie es bei Wired oder HmIP Wired aussieht, weiß ich auch nicht, da ich es nicht verwende.

Zur Zeit arbeite ich an der Version 4.4. Das ist erst mal als "Aufräumrelease" gedacht, bei dem ich einiges rauswerfe, was veraltet, historisch gewachsen oder einfach überflüssig ist. Allerdings werden schon einige Verbesserungen hinsichtlich Abfrage von CCU Infos enthalten sein.

Kommt die Tage ...
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 28 Dezember 2019, 00:38:15
Bin schon gespannt. Ich habe mit meiner CCU2 einmal gespielt.
Ziel ist es, die Register und Enums "einzulagern" welche für das jeweilige Device interessant, also definiert sind.
Mit der Routine unten klappt das und ist so geordnet, wie ich es mir vorstelle. Man kann es verkürzen, wenn die enthaltenen entity spezifischen Daten separat abgefragt werden (macht m.E. sinn).
Es kostet 0 Zeit, wenn bspw der Wert ccutype auf vorhanden sein in $HMCCU_DevDef überprüft wird. Die Implementierung hängt von den Ablauf der Definition der Entity ab.

Aber wenn du alles auf einen Rutsch bekommst ist es effizienter.

Weiter habe ich bei den ersten Kommandos welche ich probiert habe festgestellt, dass man die Nummern der Devices eingeben muss um ein Resultat zu erhalten.
Also
Zitatget HMccu deviceinfo <serialnumber>
Das sollte nie der Fall sein. Wir haben Namen für die Devices. Allerdings würde ich das Kommando "get deviceinfo" in der HMCCU schlicht löschen. Das kanna man in der channel-entity ausführen.
Und wo wir bei deviceinfo sind:

Ich bekommen
ZitatCHN 0001D7098D99DC:0 HCCpsm1:0
  DPT {f} HmIP-RF.0001D7098D99DC:0.ACTUAL_TEMPERATURE = 0.000000 [RE]
  DPT {b} HmIP-RF.0001D7098D99DC:0.CONFIG_PENDING = false [RE]
  DPT {b} HmIP-RF.0001D7098D99DC:0.DUTY_CYCLE = false [RE]
  DPT {n} HmIP-RF.0001D7098D99DC:0.ERROR_CODE = 0 [RE]
.....
CHN 0001D7098D99DC:1 HCCpsm1Btn
  DPT {b} HmIP-RF.0001D7098D99DC:1.PRESS_LONG =  [E]
  DPT {b} HmIP-RF.0001D7098D99DC:1.PRESS_SHORT =  [E]

Ich will es komprimierter - und nur die Daten dieses Kanals
Zitat
CHN 0001D7098D99DC:0 HCCpsm1:0
  [RE] ACTUAL_TEMPERATURE = 0.000000
  [RE] CONFIG_PENDING = false
  [RE] DUTY_CYCLE = false
  [RE] ERROR_CODE = 0
.....
Wobei eine Methode die aktellen Werte und eine die Möglichkeiten ( min/max/unit/enums) darstellen sollte. 

Ich warte auf deinen neuen code - zum Ausprobieren.  :)

Routine nur für BidCos....
sub HMCCU_getDeviceDefs ($)
{
my ($name)  = @_;  # address of the entity - i.e. the serial number
my $hash    = $defs{$name}; 
my $DefAddr = $hash->{DEF};  # address of the entity - i.e. the serial number
    my ($Serial) = split(":",$DefAddr); #separate the serial number
my $hmccu_hash = HMCCU_GetHash ($hash);#
    my $rpchash = $defs{$hmccu_hash->{hmccu}{interfaces}{"BidCos-RF"}{device}};
    my $res="";
   
    my $res =HMCCURPCPROC_SendRequest ($rpchash,"getDeviceDescription", $Serial , "MASTER");
    my $model = $res->{TYPE};
    my $justEntitiesData = defined $HMCCU_DevDef{$model}?1:0; # we also need dynamic data. To be implemented
    foreach my $k (keys %$res) {
      if ($k =~ m/(ADDRESS|INTERFACE|FIRMWARE)/){## todo: add this to dynamic data
        next;
        }
      elsif ($k =~ m/(TYPE|VERSION|PARENT)/ ||
             $justEntitiesData){
        next;
        }
      elsif($k eq "CHILDREN"){
        $HMCCU_DevDef{$model}{$k} = scalar @{$res->{$k}};
        }
      elsif($k eq "PARAMSETS"){
        @{$HMCCU_DevDef{$model}{$k}} = @{$res->{$k}};     
        }
      else{
        $HMCCU_DevDef{$model}{$k} = $res->{$k};
        }
      }
    for (my $ch = 0;$ch < $HMCCU_DevDef{$model}{CHILDREN};$ch++){
      $res = HMCCURPCPROC_SendRequest ($rpchash,"getDeviceDescription", $Serial.":".$ch , "MASTER");
      my $Type = $res->{TYPE}; # this is the type of channel for this device
      my $justChanDedData = defined $HMCCU_DevDef{$model}{ChDef} && defined $HMCCU_DevDef{$model}{ChDef}{$Type} ? 1 : 0;
      foreach my $k (keys %$res) {
        #AES_ACTIVE=0
        if ($k =~ m/(AES)/){## todo: add this to dynamic data
          next;
          }
        elsif ($justChanDedData ||
               $k =~ m/(TYPE|VERSION|ADDRESS|PARENT|INDEX)/){## todo: add this to dynamic data
          next;
          }
        elsif($k eq "PARAMSETS"){
          @{$HMCCU_DevDef{$model}{ChDef}{$Type}{$k}} = @{$res->{$k}};     
          }
        else{
          $HMCCU_DevDef{$model}{ChDef}{$Type}{$k} = $res->{$k};
          }
        }
      next if ($justChanDedData); # no parameter description - we alrady have it
      foreach my $k (@{$HMCCU_DevDef{$model}{ChDef}{$Type}{PARAMSETS}}) { # foreach paramset
        my $res2 = HMCCURPCPROC_SendRequest ($rpchash,"getParamsetDescription", $Serial.":".$ch,$k  );
        foreach my $var (keys %$res2){
          foreach my $varAttr (keys %{$res2->{$var}}){
            if ($varAttr =~ m/(ID)/){
              next;
              }
            elsif($var eq "SPECIAL"){
              #todo: have to implement this.       
              }
            elsif($var eq "VALUE_LIST"){
              @{$HMCCU_ParamDesc{$var}{$k}} = @{$res->{$k}};     
              }
            else{
              $HMCCU_ParamDesc{$var}{$k} = $res->{$k};
              }
            }
          }
        }
      }
}
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 28 Dezember 2019, 13:06:55
Und ein weiteres Thema (sorry, dich zu überfluten, meine ungedult ;) )

Es geht um die Synchronisation der Entites. Die CCU hat einiges mehr, hier erst einmal die physikalischen Geräte:
Meine Philosophie
- Nutze ich FHEM will ich alle (ALLE) Geräte der CCU in FHEM sehen. Ich denke (nein, ich weiss) man kann auch das Pairen in FHEM bewerkstellgen - lasse ich aussen vor. Reicht wenn ich vorerst in der CCU paire. Dann aber muss alles nach FHEM gespiegelt werden. Semi-Automatisch. Das Kommando muss einfach sein - was in FHEM heisst: nur ein (EIN!) parameter. keine Filter! (ich hatte in hmInfo auch Filter - mittlerweile gibt es die Kommandos "simplified")
-> Ich stelle mir also ein Kommando vor
Zitat- get/set HMccu deviceList [verify|createDev|createChn|update]
      * das Verify prüft, ob CCU-entites in FHEM existieren. Da du sicher nicht von HMCCUDEV ablassen willst musst du es "smart"  implementieren:
          a) die Liste aller CCU entites wird gelesen. Bspw ein listDevices mit grep auf die Adressen.
          b) prüfen welche Adressen in FHEM instanziiert sind. Sollte HMCCUDEV existieren sind alle Kanäle abgedeckt. Existieren HMCCUCHN entites sind alle Kanäle einzeln zu verifizieren
          c) Ausnahme: Die 50 (virtuellen) Kanäle der Zentrale würde ich ausklammern
          d) Ausgegeben wird die Unterschiedsliste. Entites welche in FHEM, nicht aber in der CCU und umgekehrt existieren
       * createDev: alle fehlenden Devices werden als HMCCUDEV creiert. Keine weiteren optionen. Alles was noch notwendig ist kommt nachher, incl der (smarten) Namensvergabe
       * createChn: alle fehlenden channeld werden als HMCCUCHN creiert. Keine weiteren optionen. Alles was noch notwendig ist kommt nachher.
         - Ein Kommando deviceRename wie in CUL_HM wäre praktisch. Hier werden alle Kanäle eines Device umbeannnt - also Devicename.channelextention
          - Der kanal 0 (maintenance) beinhaltet auch die allgemeinen Device-Informationen und Readings. Macht sinn, da es diese immer gibt und er sowieso "zentral" ist.
       * update: alle "existierenden!" DEV/CHN erfahren einen Update. Will sagen die Konfigurations-attribute (readings) werden mit der CCU abgeglichen. Verify sollte hier auch unterschiede/abweichungen anzeigen
+ Das Kommando lösche keine FHEM instanzen,macht der User nach "verify" manuell
+ Das erstellen der Entites erfolgt nach best-guess. Also alles was du meinst, dass Sinn macht - aber keine User Optionen.
+ Das Kommando sollte sich explizit und ausschliesslich auf Description-daten beziehen(siehe unten). Operationelle/Config Daten müssen mit anderen Kommandos abgedekt werden
bezogen auf das obige Kommando müssen wir wieder einmal definitionen vereinbaren

Wäre cool wenn du eine Liste der Definitionen pflegen könntest. Aus meiner Sicht ist das immer die Basis einer Diskussion - aber auch meines Denkens. Hilft mir selbst und anderen.

P.S. in CUL_HM musste ich nicht zwischen Description und Config unterschieden. Der Unterschied bei CCU ist die CCU. Du hast eine weitere Zwischen- Instanz welche Änderungen vornehmen kann. Somit würde ich hier unbedingt eine Unterscheidung vornehmen.
P.S. natürlich werde ich am Ende ein Kommando erwarten, welche alles mit einem Click prüft (hmInfo checkConfig). Aber erst einmal braucht man es getrennt
P.S. wäre schön, wenn man sich in Teilen an CUL_HM anlehnen könnte. Erst einmal halte ich das Kozept für ... zumindest ok. Weiter kann man den Umstieg vereinfachen, wenn sich die User wiederfinden.
Mir ist seit den Erscheinen der ersten HM-IP devices klar, dass CUL_HM ein Auslaufmodell ist.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: kjmEjfu am 28 Dezember 2019, 16:29:08
Ich habe ehrlich gesagt keine Ahnung, was dieser ganzer Kram mit den Entitäten für einen Vorteil hat.
Aber ich habe - vielleicht auch deshalb - eine Bitte: eventuelle Umbauten am Modul bitte möglichst minimalinvasiv oder rückwärtskompatibel durchführen  :)
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 28 Dezember 2019, 17:25:37
Hi KjmEjfu.
Zap wird darauf achten.
Ich für meinen Teil werde wir gesagt mir der aktuellen Implementierung nicht leben. Aktuell reden wir über interne Strukturen und Methoden , welche erst einmal eben intern sind.
Sollten die Auswirkungen größer sein und nicht als add-on sondern "nur" zusätzliche funktionen bieten ist alles klar. Sollten andere Änderungen notwendig sein (so weit not garnicht ausgemacht!!!) kann man eine neue Version erstellen und diese alternativ einpflegen.

Das Modul ist gut - und mit Sicherheit zukunftsweisend. Allerdings aus meiner Sicht zu kompliziert und fragil. Es lässt sehr viel zu, nutzt zu wenig Info welche von der CCU geliefert werden sollte (muss). Also eine hervorragende Basis, noch kein Endprodukt.
Die Entscheidung muss zap treffen.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 28 Dezember 2019, 17:33:53
Hi Zap, ich habe meine Prozedur die Device-Daten zu erfassen einmal ausgemessen. Nach 14s brutto habe ich 80 entities geprüft, 14 komplett eingelesen, also die Description (besser specification? Ich glaube dasnutzt du als Begriff) eingelesen.
Das halte ich erst einmal für ok. Installationen mir deutlich mehr devices nutzen doch immer wieder gleiche Typen. Mehr als 20 Device typen (models) sind unwahrscheinlich. Mehr entites kosten keine Zeit, Tipisch noch nicht einmal eine einzige Anfrage an der ccu (also noch schneller).

Aus meiner Sicht ist eine Funktion wie gepostet also kein Performance Problem. Die Abfrage erfolgt schlieslich nur einmal je FHEM boot je deviceTyp

Ich bin auf deine erste Test - version gespannt. Bitte posten wenn verfügbar.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 29 Dezember 2019, 18:21:47
Hi Martin,

vielen Dank für den Code-Beitrag. Hilft. Ich möchte nicht zu viel auf einmal ändern. Gerade die CCU Zugriffe haben immer wieder für Probleme gesorgt (Timeouts bis hin zum Abschießen des HMIPServer Prozesses auf der CCU). Dennoch wird die 4.4 bereits eine Menge zusätzlicher Infos aus der CCU intern abspeichern. Bin aber immer noch am testen. Leider verhält sich nicht alles so, wie von EQ-3 dokumentiert. Werte, die angeblich immer vorhanden sind, fehlen bei einigen Device Types.

Nur nochmal damit wir vom gleichen reden: Die CCU bietet 2 Zugriffsebenen: 1. ReGa, 2. RPC.

Die ReGa Schnittstelle hat 2 große Vorteile:
1. Mit Homematic Script hat man viele Möglichkeiten, auf die CCU zuzugreifen oder Informationen abzufragen
2. Die Daten kommen (beim Lesen) von der CCU und belasten nicht den Duty Cycle (das ist aber auch ein Nachteil, da die Daten nicht immer top-aktuell sind)

Die RPC Schnittstelle hat vor und Nachteile:
+ RPC Requests sind schneller als Homematic Script Anfragen
+ Mit RPC Requests kann man Dinge tun, die mit HM-Script nicht gehen (Geräte verknüpfen)
- Viele RPC Requests gehen direkt bis zum Gerät und belasten damit den Duty Cycle. Davor warnt sogar Eq-3 in der RPC Doku

Doku für Wired und BidCos-RF: https://www.eq-3.de/Downloads/eq3/download%20bereich/hm_web_ui_doku/HM_XmlRpc_API.pdf

Doku addon für HMIP: https://www.eq-3.de/Downloads/eq3/download%20bereich/hm_web_ui_doku/HMIP_XmlRpc_API_Addendum.pdf

BTW: Mittlerweile habe ich festgestellt, dass die CCU an einen registrierten RPC Server (HMCCURPCPROC) die DeviceDescription frei haus liefert. Die Info muss also nicht explizit abgefragt werden. Die ParamSet Infos aber schon.

Grüße
Dirk


Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 29 Dezember 2019, 19:04:41
Hallo Dirk,
Ich nutze aktuell nur das RPC inerface wie von dir implementiert - und tests, was mit die CCU preisgibt. Die Doku kenne  und nutze ich.

- das mit den Duty-Cycle der RPC Schnittstelle verstehe ich nicht. So wie ich es sehe wird nicht direkt "in die Luft gegriffen". Ich erhalten bei den Abfragen nur Daten aus der CCU. Ich kann nicht beobachten, dass etwas am Funk passiert. Warum also Duty-Cycle?
- Das mit den Scripten ist mir noch fremd. Ich muss also scripten in die CCU implementieren um zu kommunizieren? Hier würden mich Details interessieren. Wir kommen die Scripten dahin? Über FHEM?
- Ich frage bislang im Wesentlichen Config-daten ab. Die CCU cached diese - was man unbedingt berücksichtigen muss. Die Daten können uralt sein, da der Cache nie expired. Daraus resultiert: a)Wenig Funklast b) ich kann RPC nutzen ohne zu funken c) Daten sind evtl nicht aktuell d) ein clear cach ist möglich. erzeugt Funklast wenn neu gelesen wird, aber wann ist noch unklar.

Zum "urlesen" nach einem fhem -reboot oder re-connect (beides?) kann man alle Konfigurationen lesen unter nutzung von "listDevices". Ich kann dir die Funktion generieren - das geht schneller und geschmeidiger als die aktuell angebotene Funktion. Allerdings ist die Angebotene notwendig, wenn ein neuer Devicetyp gefunden/gepair/Instanziiert wurde.

ZitatLeider verhält sich nicht alles so, wie von EQ-3 dokumentiert. Werte, die angeblich immer vorhanden sind, fehlen bei einigen Device Types.
Beispiele bitte - aus dem BidCos sektor. Da bin ich besser aufgestellt.

ZitatIch möchte nicht zu viel auf einmal ändern.
Ich würde gerne in die Vollen gehen. Viele kleine Änderungen beinhalten viele Probleme und man hat am Ende viel mehr zu tun.
Allerdings brauche ich erst deine Gedanken zu einer möglichen Architektur.
Zum Einen reden wir von möglichen Änderungen in der Datenstruktur. Diese sind erst einmal für den User transparent, erlauben aber eine geordnete Programmierung. Hast du hier etwa geplant? Wird sich etwas ändern? Wie ist die Struktur der Daten gedacht?

Zum Zweiten können wir das User-Interface, besser Operator-Interface prüfen. Generell habe ich beo hmInfo auch mit "komplexen" Kommandos angefangen. Viele Filter-Möglichkeiten,.... Dann habe ich simplifizierte Kommandos eingeführt welche nur mit "click" auszuführen sind, kein Tippen. Also nur 1 Parameter, mehr gibt das Standard interface in FHEM nicht her.
Ziel sollte immer der Apple-Ansatz sein, dass ein User wenig wissen muss und sich die typischen Sachen automatisch einstellen. Nicht immer nachfragen. Im expert mode kann der geübte Operator dann nachbessern. Der Operator/User sollte mit Adressen wie Serialnumber oder RF Adresse nichts zu tun haben. Kann er sich ansehen, aber nie in ein Kommando eingeben. Das macht FHEM für ihn.

Wie ist deine Meinung?

Ich habe gerade einmal angefangen, Links und Peerings auszulesen. War zäh, jetzt habe ich erste Erfolge.

Gruß Martin


Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 29 Dezember 2019, 23:12:25
Habe mir die struktur der ccu in wiki angesehen. Kurz. Mein Eindruck und meine Präferenz ist rpc. Ich sehe die ccu als inteligentes io. Die Schicht darüber würde gerne auslassen.
In jedem Fall würde ich vermeiden beide Schnittstellen zu nutzen. Ist das möglich?
Ich will mit der Schnittstelle nicht die ccu auf Vordermann bringen sondern die devices steuern.
Die ccu liefert beste arbeit in Sachen Funk Timing, aes, msg sequenzing und caching der dp und config.

Ich habe damit nur das rpc if und fhem zu bedienen. Tcl und rega sind aussen vor.

Was ist deine strategie?
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 30 Dezember 2019, 12:57:18
So, habe einmal darüber geschlafen.
- RPC ist hinreichend für alles, was man zum Device.steuern benötigt.
- ReGa erlaubt
  - auf die Namen in der CCU zuzugreifen
  - pre-prozessing von Daten.
   ? was kann ReGa noch, ausser die Namen-zuordnung? Ok. die Description fehlt noch - sehe ich nicht in RPC
   ? wir haben Perl von FHEM in Hintergrund. Welche Scripte sind für die ReGa Schnittstelle wirklich notwendig?

Performance-mäßig sehe ich keinen Unterschied zwischen den Schnittellen. Ethernet sollte schnell genug sein. Die ReGa Schnittstelle entlastet nicht die CCU sondern FHEM. Das ist m.E. nicht notwendig. Zustimmung?

Im HMCCUConf sehe ich eine Menge Arbeit für die Device-Definitionen. Willst du das wirklich in dieser Form aufrecht erhalten? Ich würde erwarten, dass die (wichtigen) eventMap intern durch die enmuns abgedeckt werden. Das muss dann "automatisch" aus der ccu geholt werden. Damit sind dann auch neue Devices sofort integriert.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 30 Dezember 2019, 16:21:58
Hallo Dirk,

schon wieder ich :)
Ich habe die Abfrage der Description etwas optiniert.
Eingetragen wird:
- alle in der CCU bekannten Entites (device und Kanal)
    - ihre Beschreibung (rxmode,....)
    - ihre Basis-Daten (RF-Adresse, AES-Aktiv, Firmware, Roaming)
    - dekodierte Werte (enums)
    - Parameter  Beschreibung
Das ist ein Aufruf welche ich nach INIT_DONE machen würde, also wenn alle fhem.cfg gelesen sind.
Du müsstest es noch über alle RPC interfaces "loopen".
Findest du ein neues Device kannst du es auch nur für eines aufrufen.

Für mich ist das die Basis, einmal die entites darzustellen.
  - Abgleich der Entites CCU<->fhem
  - Darstellung der Beschreibung

p.s.: Ich warte noch auf deine vorab-Version zum Testen

sub HMCCU_syncDevices ()
{
    my $rpcH = $defs{d_rpc178046BidCos_RF};
    my $r = HMCCURPCPROC_SendRequest ($rpcH,"listDevices", "",""); # get all devices fro BidCos
    foreach my $h (@{$r}){ # split all entity description (devices and channels)
      HMCCU_evalDevDesc ($h,$rpcH);
      }
}

sub HMCCU_evalDevDesc ($$)
{
my ($descH,$rpcH)  = @_;  # hash to device description
    my %FLAGSdev  = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x08 => "DontDelete"
          );
    my %DIRECTION  = (
           0 => "NONE"
          ,1 => "SENDER"
          ,2 => "RECEIVER"
          );
    my %RX_MODE = (
           0x01 => "ALWAYS"
          ,0x02 => "BURST"
          ,0x04 => "CONFIG"
          ,0x08 => "WAKEUP"
          ,0x10 => "LAZY_CONFIG"
          );
    my %FLAGSparam = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x04 => "Transform"
          ,0x08 => "Service"
          ,0x10 => "Sticky"
          );
     
     
    my $addr  = defined $descH->{ADDRESS}    ? $descH->{ADDRESS}     : $descH->{PARENT};
    my $idx   = defined $descH->{INDEX}      ? $descH->{INDEX}       : "dev";           # channel number
    my $model = defined $descH->{PARENT_TYPE}? $descH->{PARENT_TYPE} : $descH->{TYPE}  ;# identify model for channel and device
    my $chTyp = defined $descH->{INDEX}      ? $descH->{TYPE}        : "dev";           # if not channel then chTyp = dev
    my $entDataOnly = (defined $HMCCU_DevDef{$model} && defined $HMCCU_DevDef{$model}{$chTyp}) ? 1 : 0; # no need for model description - already available
    foreach my $k (keys %$descH){
      my $devLevel = defined $descH->{ADDRESS} ? "dev" : "chn";
      if ($entDataOnly || $k =~ m/(^ADDRESS|TYPE|VERSION|PARENT|INDEX)/ ){ ## ignore this
        next;
        }
      elsif ($k =~ m/(RF_ADDRESS|INTERFACE|FIRMWARE|AES|ROAMING)/){## todo: add this to dynamic data
        $HMCCU_EntData{$addr}{$idx}{$k} = $descH->{$k};
        }
      elsif($k eq "CHILDREN"){
        $HMCCU_DevDef{$model}{$chTyp}{$k} = scalar @{$descH->{$k}};
        }
      elsif($k eq "PARAMSETS"){
        @{$HMCCU_DevDef{$model}{$chTyp}{$k}} = @{$descH->{$k}};     
        }
      elsif($k eq "FLAGS"){
        foreach (keys %FLAGSdev){
          $HMCCU_DevDef{$model}{$chTyp}{$k}{$FLAGSdev{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "RX_MODE"){
        foreach (keys %RX_MODE){
          $HMCCU_DevDef{$model}{$chTyp}{$k}{$RX_MODE{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "DIRECTION"){
        $HMCCU_DevDef{$model}{$chTyp}{$k} = $DIRECTION{$descH->{$k}};
        }
      else{
        $HMCCU_DevDef{$model}{$chTyp}{$k} = $descH->{$k};
        }
      }

    return if ($entDataOnly); # only once required
   
    foreach my $k (@{$HMCCU_DevDef{$model}{$chTyp}{PARAMSETS}}) { # foreach paramset
      my $res = HMCCURPCPROC_SendRequest ($rpcH,"getParamsetDescription", $addr.":".$idx,$k  );
      foreach my $var (keys %$res){
        my $logme= "";
        foreach my $varAttr (keys %{$res->{$var}}){
          if ($varAttr =~ m/(ID)/){
            next;
            }
          elsif($varAttr eq "SPECIAL"){
            foreach my $x (@{$res->{$var}{$varAttr}}){
              foreach my $tp (keys %{$x}){
                $HMCCU_ParamDesc{$var}{$varAttr}{$tp} = $x->{$tp};
                }
              }
            }
          elsif($varAttr eq "VALUE_LIST"){
            @{$HMCCU_ParamDesc{$var}{$varAttr}} = @{$res->{$var}{$varAttr}};           
            }
          elsif($varAttr eq "FLAGS"){
            foreach (keys %FLAGSparam){
              $HMCCU_ParamDesc{$var}{$varAttr}{$FLAGSparam{$_}} = 1 if($_+0 & $res->{$var}{$varAttr}+0);
              }
            }
          else{
            $HMCCU_ParamDesc{$var}{$varAttr} = $res->{$var}{$varAttr};         
            }
          }
        }
      }
}
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 31 Dezember 2019, 09:45:46
Hi Martin,

zur Device Description:

Der "listDevices" Befehl muss nicht explizit aufgerufen werden. Das macht HMCCURPCPROC beim Starten des RPC Servers. Die CCU reagiert darauf mit "NewDevices" Events, die ein Array mit den Device Descriptions enthalten. Dann kommt HMCCU_UpdateDeviceTable (oder so ähnlich) zum Zug, das die Informationen im Hash vom IO Device ablegt (derzeit noch nicht alle). An der Stelle hänge ich im Moment, da die RPC Server als separate Prozesse laufen und etwas im Speichermanagement schief geht. Witzigerweise scheint das noch nie funktioniert zu haben ;)

UPDATE: Wieder mal auf die Doku verlassen und verloren. Man muss doch die Geräte explizit mit listDevices abfragen. Theorie: Die CCU ruft listDevices in HMCCURPCPROC auf, das antwortet mit einem leeren Array woraufhin die CCU für jedes Gerät einen newDevice Event schickt. Macht sie aber nicht :(

HMCCUConfig

Möchte ich mittelfristig loswerden. Habe bereits damit begonnen, auf FHEM Config Templates umzustellen, die auch von anderen Modulen bereits verwendet werden. Da kann man mit einer Definition gleich mehrere Device Types erschlagen.

ReGa vs. RPC

Über die Schnittstelle kommt man an die ganze restliche Logik dran, z.B. Räume, Kategorien (Licht, Heizung, usw). Man kann Programme ausführen, Systemvariablen lesen / schreiben usw. Für HMCCU essentiell sind die Gerätenamen. Sonst müsste man bei jeder Kanal- und Device-Definition in FHEM immer die Adresse kennen und angeben. Finde ich für den Nutzer etwas unhandlich.
RPC taugt hingegen zum Lesen / Schreiben von Datenpunkten und eben dem Auslesen der Device- und Paramset-Beschreibung => Für diese Zwecke brauchst Du also keine ReGa.
Ein großer Vorteil der ReGa ist, dass Zugriffe nicht zwingend zu einer Kommunikation zwischen CCU und dem Gerät führen (Duty Cycle). Bei RPC kommt das deutlich häufiger vor, siehe auch die entsprechenden Hinweise bei einzelnen RPC Methoden in der EQ-3 Doku. Mir ist nicht klar, ob die CCU auch bei anderen Requests von Zeit zu Zeit aktiv die Geräte fragt und wenn ja, nach welchen Kriterien (Alter der Informationen?) das passiert.

Homematic Script

Es gibt zwei Möglichkeiten, Homematic Script in der CCU auszuführen:
1. Man erstellt ein Programm in der CCU, das wiederum HM-Script Code enthält
2. Man schickt den Script Code per HTTP POST an die ReGa, die den Code ausführt
HMCCU unterstützt zwar beide Varianten, nutzt für die Kommunikation jedoch 2. Die Scripte findest Du in HMCCUConf.pm.

Weitere Planung meinerseits (erste Gedanken)

1. Ich werde versuchen, soviele Infos zu den Device Types wie möglich bereits in der anstehenden Version abzufragen und im internen Hash vom IO Device zu speichern. Dazu werde ich die schon vorhandenen Strukturen nutzen und erweitern:
$hash->{hmccu}{dev} und/oder $hash->{hmccu}{dp}
An der Stelle habe ich noch keine Idee, wie ich damit umgehe, dass mit einem Firmware Update neue Datenpunkte hinzukommen oder sich (eher selten) Wertemengen ändern. Gerade bei neuen HmIP Geräten kommt das öfters vor. Muss HMCCU dann auch noch die ältere Firmware Version unterstützen?

2. Nutzung von Config Templates anstelle der Defaults aus HMCCUConf.pm

3. Automatisches Setzen einiger Attribute bei der Definition von Devices, sofern bestimmte Funktionalitäten aus der Device Description ableitbar sind (z.B. LEVEL, STATE, SET_TEMPERATURE vorhanden => automatisch als state/control Datapoint setzen). Das erspart dem User zumindest bei den gebräuchlichsten Geräten die Attribut-Hölle.

Ich denke / hoffe, 1. hilft Dir erst mal am meisten.

Etwas Geduld bitte noch. Ich muss noch den listDevice/newDevices Bug beseitigen.

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 31 Dezember 2019, 12:40:56
Hi Dirk,
Ungeduldig bin ich immer. Aber das ist kein primäres Problem.
Mir ist technisch unklar, was rpc mit dutycycle zu tun hat. Ach hier kommen die daten aus dem cache. Man kann diesen löschen,....  Aber warum rega besser sein soll kann ich nicht erkennen. Ich sehe auch keine Aktivitäten am Funk. Und nur hier gibt es dutycycle.
Rega hat zugriff auf die höheren level. Und wieder kenne ich deine Philosophie und Zielen nicht. In der ccu  kann man Räume usw definieren. Das interessiert mich nicht. Ich habe Räume in fhem. Ich wil nicht die gesamte funktion der ccu abbilden. Auch will ich kein gemischtes system. So wenig ccu als möglich.
Die namen sind notweñdig, also brauche ich rega. Sicher kommt noch etwas.

Ich habe nun fast eine version zum lesen aller device config und register. Die enums sind implementiert. Heute bekomme ich voraussichtlich keine zeit :( .wenn es fertig ist schicke ich es dir.
Neue devices müssen m.e. nicht automatisch erkannt werden. Schön wenn es geht, aber ein sync kommando sollte auch reichen. So oft kommt es nicht vor. Schon gar nicht plötzlich. Ist also prio 3.

Gruss Martin
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 31 Dezember 2019, 16:37:03
Hallo Martin,

noch ein Tipp: Wenn Du bei HMCCURPCPROC Devices im Attribut ccuflags das Flag expert setzt, hast Du den zusätzlichen set Befehl rpcrequest.

Damit kannst Du jeden RPC Request ausführen. Das Ergebnis wird im FHEM Fenster gedumpt.

Also z.B.

set d_rpcBidCos rpcrequest getDeviceDescription LEQ0919881
set d_rpcBidCos rpcrequest listDevices
set d_rpcBidCos rpcrequest getParamsetDescription LEQ0919881:1 VALUES

Mittlerweile denke ich an eine Speicherung der Art:

$hash->{hmccu}{dev}: Hier kommen die ganzen Device spezifischen Sachen rein, also z.B. Version und Firmware
$hash->{hmccu}{mod}{version/firmware}: Für die Devicemodel spezifischen Dinge (z.B. die ParameterSet Beschreibungen).

$hash->{hmccu}{dp} behalte ich aus Kompatibilitätsgründen erst mal bei, bis ich alle internen Funktionen umgestellt habe. Das kostet sonst zu viel Aufwand.

Um die Unterscheidung nach Firmware/Version wird man nicht herumkommen. Wenn ein Nutzer unterschiedliche Firmwarestände bei gleichen Geräten hat, gibt's sonst Probleme.

Grüße
Dirk

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 31 Dezember 2019, 17:25:58
Hallo Dirk,

wo fange ich an.
Nachstehender Code liest alle Device configs aus. Du musst die globalenVariable eintragen. Die Subroutines einfach am Ende hineinkopieren.
Sicher erzähle ich die schon bekanntes :)

Die Hashes der RCP Schnittstelle hole ich noch nicht automatisch. Du musst an 2 Stellen
"$defs{d_rpc178046...}"
ersetzen. Muss natürlich noch geändert werden.
Ich mache dann ein
reload reload 88_HMCCU.pm

Ich arbeite in einem Terminal-Fenster. Angenehmer als die Web-Commandline, aber funktional identisch.
Dann, um die Definitionen der (aller) CCU entites zu lesen mache ein
{HMCCU_syncDevices ()}
Jetzt kannst du es testen.
{HMCCU_params(<entityName>)}
<entityName> ist der Name eines Kanals, also HMCCUCHN. DEV interessiert mich immer noch nicht.

Du erhältst alle Peerings und Register - in einer noch schlechten formatierung. Alle enums sind eingetragen. "Specials" noch nicht.

HMCCU_ParamDesc: Definition eines Parameters, min, max,... Das ist nicht model-spezifisch
HMCCU_DevDef: Definition eines Devices
    HMCCU_DevDef{<model>}{<channelType>}{<variable>} = value
    <channelType>: für das Device selbst, welchen keinen Typ hat setze ich "dev"
    Wenige Variable sind keine Werte sondern bspw ein Array
HMCCU_EntData: hier habe ich die Entity data
    HMCCU_EntData{<serial>}{<chn>}{<var>} = <value>
   <serial>: Seriennummer oder auch Addresse - verwende ich synonym
   <chn>: Nummer des Kanals. Es gibt immer 0 und 1. Dann bis zu 50. "dev" setze ich für das Device, welches kein Kanal ist.
   <var>: variable mit dem <value>

Ich würde dich bitten, die Struktur beizubehalten. Das kann man dann automatisch "befüllen"

Wenn du alles im HMCCU hash halten willst ist das ok. Sehe ich dann so:
$hash->{hmccu}{dev}: HMCCU_EntData
$hash->{hmccu}{mod}: HMCCU_DevDef
$hash->{hmccu}{par}: HMCCU_ParamDesc



#---Insert MPI---
use vars qw(%HMCCU_DevDef);
use vars qw(%HMCCU_ParamDesc);
use vars qw(%HMCCU_EntData);

my %HMCCU_DevDef;
my %HMCCU_ParamDesc;
my %HMCCU_EntData;

sub HMCCU_syncDevices ()
{
    my $rpcH = $defs{d_rpc178046HmIP_RF};
    foreach my $rpcH ($defs{d_rpc178046HmIP_RF},$defs{d_rpc178046BidCos_RF}){
      my $r = HMCCURPCPROC_SendRequest ($rpcH,"listDevices", "",""); # get all devices fro BidCos
      foreach my $h (@{$r}){ # split all entity description (devices and channels)
        HMCCU_evalDevDesc ($h,$rpcH);
        }
      }
    HMCCU_ccuNames();
}

sub HMCCU_evalDevDesc ($$)
{
my ($descH,$rpcH)  = @_;  # hash to device description
    my %FLAGSdev  = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x08 => "DontDelete"
          );
    my %DIRECTION  = (
           0 => "NONE"
          ,1 => "SENDER"
          ,2 => "RECEIVER"
          );
    my %RX_MODE = (
           0x01 => "ALWAYS"
          ,0x02 => "BURST"
          ,0x04 => "CONFIG"
          ,0x08 => "WAKEUP"
          ,0x10 => "LAZY_CONFIG"
          );
    my %FLAGSparam = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x04 => "Transform"
          ,0x08 => "Service"
          ,0x10 => "Sticky"
          );
     
     
    my $addr  = defined $descH->{ADDRESS}    ? $descH->{ADDRESS}     : $descH->{PARENT};
    my $idx   = defined $descH->{INDEX}      ? $descH->{INDEX}       : "dev";           # channel number
    my $model = defined $descH->{PARENT_TYPE}? $descH->{PARENT_TYPE} : $descH->{TYPE}  ;# identify model for channel and device
    my $chTyp = defined $descH->{INDEX}      ? $descH->{TYPE}        : "dev";           # if not channel then chTyp = dev
    my $entDataOnly = (defined $HMCCU_DevDef{$model} && defined $HMCCU_DevDef{$model}{$chTyp}) ? 1 : 0; # no need for model description - already available
    $HMCCU_EntData{$addr}{dev}{MODEL} = $model;
    $HMCCU_EntData{$addr}{$idx}{CHTyp} = $chTyp;
    foreach my $k (keys %$descH){
      my $devLevel = defined $descH->{ADDRESS} ? "dev" : "chn";
      if ($entDataOnly || $k =~ m/(^ADDRESS|TYPE|VERSION|PARENT|INDEX)/ ){ ## ignore this
        next;
        }
      elsif ($k =~ m/(RF_ADDRESS|INTERFACE|FIRMWARE|AES|ROAMING)/){## todo: add this to dynamic data
        $HMCCU_EntData{$addr}{$idx}{$k} = $descH->{$k};
        }
      elsif($k eq "CHILDREN"){
        $HMCCU_DevDef{$model}{$chTyp}{$k} = scalar @{$descH->{$k}};
        }
      elsif($k eq "PARAMSETS"){
        @{$HMCCU_DevDef{$model}{$chTyp}{$k}} = @{$descH->{$k}};     
        }
      elsif($k eq "FLAGS"){
        foreach (keys %FLAGSdev){
          $HMCCU_DevDef{$model}{$chTyp}{$k}{$FLAGSdev{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "RX_MODE"){
        foreach (keys %RX_MODE){
          $HMCCU_DevDef{$model}{$chTyp}{$k}{$RX_MODE{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "DIRECTION"){
        $HMCCU_DevDef{$model}{$chTyp}{$k} = $DIRECTION{$descH->{$k}};
        }
      else{
        $HMCCU_DevDef{$model}{$chTyp}{$k} = $descH->{$k};
      }
    }
    $HMCCU_DevDef{$model}{$chTyp}{LinkRole} = $HMCCU_DevDef{$model}{$chTyp}{LINK_SOURCE_ROLES} ne "" ? "source"
                                             :$HMCCU_DevDef{$model}{$chTyp}{LINK_TARGET_ROLES} ne "" ? "target"
                                             :"none";
   
    return if ($entDataOnly); # only once required
   
    foreach my $k (@{$HMCCU_DevDef{$model}{$chTyp}{PARAMSETS}}) { # foreach paramset
      my $res = HMCCURPCPROC_SendRequest ($rpcH,"getParamsetDescription", $addr.":".$idx,$k  );
      foreach my $var (keys %$res){
        if ($var =~ m/fault/){
          Log 1,"General go a fault $addr : $idx : $model";
          next;
        }
        foreach my $varAttr (keys %{$res->{$var}}){
          if ($varAttr =~ m/(ID)/){
            next;
            }
          elsif($varAttr eq "SPECIAL"){
            foreach my $x (@{$res->{$var}{$varAttr}}){
              foreach my $tp (keys %{$x}){
                $HMCCU_ParamDesc{$var}{$varAttr}{$tp} = $x->{$tp};
                }
              }
            }
          elsif($varAttr eq "VALUE_LIST"){
            @{$HMCCU_ParamDesc{$var}{$varAttr}} = @{$res->{$var}{$varAttr}};           
            }
          elsif($varAttr eq "FLAGS"){
            foreach (keys %FLAGSparam){
              $HMCCU_ParamDesc{$var}{$varAttr}{$FLAGSparam{$_}} = 1 if($_+0 & $res->{$var}{$varAttr}+0);
              }
            }
          else{
            $HMCCU_ParamDesc{$var}{$varAttr} = $res->{$var}{$varAttr};         
            }
          }
        }
      }
}

sub HMCCU_ccuNames (){
    my $hash = $defs{HMccu};
my $response = HMCCU_HMScriptExt ($hash, "!GetDeviceList", undef, undef, undef);

return if ($response eq '' || $response =~ /^ERROR:.*/);

my @scrlines = split /[\n\r]+/,$response;
foreach my $hmdef (@scrlines) {
      my @hmdata = split /;/,$hmdef;
      next if (scalar ((@hmdata) == 0) || ($hmdata[0] != m/^[CD]/));
      my $addr = $hmdata[0] eq "C" ? $hmdata[1] : $hmdata[2];
      my $name = $hmdata[0] eq "C" ? $hmdata[2] : $hmdata[3];
      $HMCCU_EntData{$addr}{ccuName} = $name;
    }
}

sub HMCCU_params($)
{
my ($name)  = @_;  # address of the entity - i.e. the serial number
    my $rpcIf = $defs{d_rpc178046BidCos_RF};
    my $addr = $defs{$name}{ccuaddr};
    return "$name is undefined" if(!defined $defs{$name}
                                 ||!defined $defs{$name}{ccuaddr});
    return "$name not found in CCU" if(!defined $HMCCU_EntData{$addr});
    my ($devAddr,$idx) = split(":",$addr);
    $idx = "dev" if (!defined $idx);

    my $res="    addr:$addr";
    $res .= "\ndev:$_  : ".$HMCCU_EntData{$devAddr}{dev}{$_} foreach (sort keys %{$HMCCU_EntData{$devAddr}{dev}});
    $res .= "\n    $_  : ".$HMCCU_EntData{$addr}{$idx}{$_}   foreach (sort keys %{$HMCCU_EntData{$addr}{$idx}});
    $res .= "\n";

    my @addrList = ($addr);
    push @addrList,$devAddr if ($HMCCU_EntData{$addr}{$idx}{CHTyp} eq "MAINTENANCE");
    foreach my $dispAddr (@addrList){
      my ($dispSer,$dispIdx) = split(":",$dispAddr);
      $dispIdx = "dev" if (!defined $dispIdx);
      my $model = $HMCCU_EntData{$dispAddr}{dev}{MODEL};
      my $CHTyp = $HMCCU_EntData{$dispAddr}{$dispIdx}{CHTyp};
      my $role  = defined $HMCCU_DevDef{$model}{$CHTyp}{LinkRole} ? $HMCCU_DevDef{$model}{$CHTyp}{LinkRole} : "none";

      foreach my $ps (@{$HMCCU_DevDef{$model}{$CHTyp}{PARAMSETS}}){
        Log 1,"General now type $dispSer/$dispAddr : $ps : role:$role - $model: $CHTyp";
        my @peers;
        my @psList;
        if($ps eq "LINK"){ # with link we have to search each peer
          my $rl = HMCCURPCPROC_SendRequest ($rpcIf,"getLinks", $dispAddr, "");
          my $sStr = $role eq "source" ? "RECEIVER" : "SENDER";
          foreach my $hl (@{$rl}){
            push @peers, map{$hl->{$_}} grep /$sStr/,keys %$hl;
          }
          next if(scalar (@peers) == 0 || $role eq "none");
          Log 1,"General my peers :".join(",",@peers);
          @psList = @peers;
        }
        else{
          push @psList,$ps;
        }
        foreach my $psL (@psList){
          my $r = HMCCURPCPROC_SendRequest($rpcIf,"getParamset", $dispAddr, $psL);
          foreach my $k (sort keys %$r) {
            next if($k =~ m/(faultCode|faultString)/);
            my $val = $r->{$k};
            $val = $HMCCU_ParamDesc{$k}{VALUE_LIST}[$val] if (defined $HMCCU_ParamDesc{$k}{VALUE_LIST}
                                                          && scalar @{$HMCCU_ParamDesc{$k}{VALUE_LIST}} >= $val);
            $res .= " $dispIdx   $psL: $k = $val\n";
          }
        }
      }
    }
    return $res;
}
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 31 Dezember 2019, 17:45:58
So hört sich das sehr gut an.
Allerdings bin ich mir bei ein paar deiner Bemerkungen über deine Ziele immer noch unsicher.
Hier ein paar meiner ziele und Definitionen:
1) ich sehe die ccu als intelligentes io. In keinem Fall als Controller. Fhem ist der Controller!
=》 mich interessieren keine Räume der ccu.
=》 ich brauche die ccunames um debuggen zu können
=》ich werde Informationen über ccu alarme und queue  Status benötigen um alarme zu generieren. Fhem muss anzeigen, wenn Handlungsbedarf  besteht.

2) ich mache mir Gedanken über Duty cycle. Aber das hat nichts mit rpc zu tun. Ich habe recht viel getestet in culhm. Macht mir keine Angst.
3) im Gegensatz zu  culhm muss ich bei der ccu noch ergründen, wie der Cache der device Register funktioniert. Bei culhm konnte ich nach Belieben und Bedarf den Cache in fhem Update. Ich habe aber schon einen Ansatz gesehen, es hier gleich zu tun

4) ob ich die ccu zur aggregierung weiterer Information einsetzen muss oder sollte wird sich ergeben. Bspw  sd Team.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 02 Januar 2020, 09:57:20
Hi Dirk, ich schon wieder :)
Folgendes funktioniert bei mir schon wie ich es mir etwa vorstelle.
Zitata) Definitionen lesen
  - HMCCU_syncDevices synchronisiert CCU und FHEM. Mir gefällt der Begriff "cache" an dieser Stellt.  Wie im Kommentar beschrieben ist die Prozedur nach Init aufzurufen (man kann sich an den Event init-done hängen) Damit sind dann auch die RPC schnittstellen schon vorhanden.
  - Als Kommando kann man den re-sync der Definitionen sowie der Device-liste auch aufrufen mit entsprechender Gewichtung: anlegen fehlender Entites, Bereinigen(anlegen und löschen), verify und force (update aller devices,auch der schon angelegten)
  => Die Optionen sollten in einem Kommando der HMCCU zu Verfügung stehen
  => Ich würde explizit keine (KEINE) weiteren optionen zulassen. Das ist verwirrend. Der Anwender kann das Rename nachträglich durchführen. Ich benenne es systematisch... aber nicht unbedingt aus der CCU ableitbar. Auch Filter würde ich nicht vorsehen. Will ein Anwender einen Kanal nicht in FHEM "betreiben" kann er diesen in unused verschieben o.ä.
  ??> offen ist die Ausnahme: Die 50 Kanäle der RPC instanz würde ich nicht anlegen... oder doch?
  ??> die Kommandos habe ich xxxChn genannt damit noch platz ist für Device kommandos. Aber nicht von mir :)
  ??> eine LookupTable für <addr> => <FHEM-name> ist notwendig und muss verankert werden. die andere Richtung habe ich im Device
  => Die Geräte haben "Funktionskanäle" und einen Maintenance kanal (kanal 0). Weiter gibt es noch den "Device-kanal". Bei Channels verwalte ich kanal 0 und Device in einer Entity. Das passt zusammen und macht sinn.
  ??> Kanal 0 entspricht dann dem "Device" aus CUL_HM (fast). Hier bekommt man das Interface (RPC) her sowie die CCU (man könnte mehrere haben) . Auch zu verwalten, noch offen ist die CCU-RPC entity, welcher das Device zugeordnet ist. Diese wird für peerings notwendig sein und hat Auswirungen auf Kommunikationseigenschafften und Abläufe.
  ??> die Abfrage dauert lange. Einen Prozess zu spawnen wäre sinnvoll. Ist aber nicht besonders kritisch, da es nur bei Reboot und on-demand stattfindet. Lässliche Sünde.
  ??> external RPC ist nicht berücksichtigt.

Zitatb) Beschreibung abfragen HMCCU_paramDef
Hier bekommt man die Beschreibung der Register/Parameter einer entity. Dieses Kommando sollte in HMCCUCHN verankert werden und Return in einem separaten Fenster

Zitatb) Beschreibung abfragen HMCCU_param
Hier bekommt man die Inhalteder Register/Parameter einer entity. Dieses Kommando sollte in HMCCUCHN verankert werden.
  => Die gelesenen Werte sollte man speichern. Es ist nun so, dass diese Werte im Device vorliegen. Die CCU cached diese Daten. FHEM könnte also einen 2nd level cache anlegen. Halte ich für Sinnvoll. Diese Werte sollten aber in der Entity abgelegt werden. Wenn sie nicht existiert werden sie nicht abgelegt
  ??> die Ablage habe ich noch nicht vorgesehen
  ??> in HMCCUCHN sehe ich 2 Aufruf-schärfen: Ausgabe der Daten im FHEM-cache, wenn vorhanden und Updage-cache. Ich will immer ein kommando, FHEM und CCU zu synchronisieren.
  => Werte aus "values" müssen in Readings abgebildet werden
  => Werte aus "Links" kommen nach "helper". Eine "get <channel> regVal" gibt den Wert bei Bedarf aus. Ein "get <channel> regTable" gibt alles auf einmal aus.
  => Werte aus "Master" kommen nach "helper"
  ??> Die Peerliste muss noch besser eingebunden werden. Kommt nach readings und internals (damit man clicken kann)

ZitatNoch ein Kommentar zum Attribut "nochn0"
in meiner Welt kommt das nicht vor. Aber: Wenn du dies anbietest musst (MUSST) du aufräumen. Es gibt nichts schlechteres als falsche Werte (Readings). Mit nochn0 werden einige Readings nicht mehr upgedatet. An diesem Zeitpunkt sind diese Werte also per definition falsch. Es gilt das Verursacher-prinzip im Bezug auf Aufräumen und raus-wischen. Da du dieses attribut anbietest ist es deine Aufgabe, bereits bei der Implementiertung auch das Aufräumen zu implementieren.

Ich bastle noch weiter - allmählich habe ich eigentlich alle primären Funktionen zusammen - dank deiner guten Interfaces.
P.S.: Mir ist klar, dass du einige Details schon implementiert hast. das habe ich nicht komplett ergründet. Aber da du alles kennst kannst du die Teile welche dich interessieren sicher einfach übernehmen oder integrieren.

Wenn du die Funktionen einmal testest bekommest du einen Eindruck, wie es meiner Ansicht nach aussehen sollte.

Nun werde ich eine Pause machen und dann einmal das Setzen von Werten ansehen.


######################################################################
# HMCCU_syncDevices
# Subprocess: update device definitions
# called by - system start/restart
#     option: - Init       # read all devices and params. No device verification
#             - createChn  # create all missing channels. Dont touch existing
#             - updateChn  # create all missing channels. delete non-existing
#             - verifyChn  # report the difference between CCU and FHEM
#             - forceChn   # force reread update all parameter and create/delete entities

######################################################################

sub HMCCU_syncDevices ($)
{
my ($option)  = @_;  #
    if($option eq "forceChn"){# clear definitions first
       %HMCCU_DevDef    = ();
       %HMCCU_ParamDesc = ();
       %HMCCU_EntData   = ();
    }
    foreach my $rpcH (map{$defs{$_}}devspec2array ("TYPE=HMCCURPCPROC")){#todo: check other options
      my $r = HMCCURPCPROC_SendRequest ($rpcH,"listDevices", "",""); # get all devices
      foreach my $h (@{$r}){                                         # split all entity description (devices and channels)
        HMCCU_evalDevDesc ($h,$rpcH);
      }
    }
    HMCCU_ccuNames();
   
    if($option =~ m/(.*)Chn$/){
      my $task = $1;
      my @missingChn;
      my @obsoletChn;
      my @existChn;
      my %fhemChnH;
      $fhemChnH{$defs{$_}{DEF}} = $_ foreach(devspec2array ("TYPE=HMCCUCHN"));
      foreach(keys %HMCCU_EntData){
        if (defined $fhemChnH{$_}){
          push @existChn,$_ ;
        }
        else{
          push @missingChn,$_;
        }
      }
      foreach(keys %fhemChnH){
        push @obsoletChn,$_ if (!defined $HMCCU_EntData{$_}) ;
      };
      if($task eq "verify"){
         return "\nCCU channels not yet defined:\n   "     .join("\n   ",sort map{"$_: $HMCCU_EntData{$_}{ccuName}"} @missingChn)
               ."\nFHEM channels not esixting in CCU:\n   ".join("\n   ",sort map{"$_: $fhemChnH{$_}"} @obsoletChn)
               ."\nInSync for :\n   "                      .join("\n   ",sort map{"$_: $fhemChnH{$_} \tccuName:$HMCCU_EntData{$_}{ccuName}"} @existChn)
                ;
      }
      elsif($task =~ m/(create|update|force)/){
        foreach my $addr (@missingChn){
          # Define new client device
          my $ret = CommandDefine (undef, "$fhemChnH{$defs{$addr}{DEF}} HMCCUCHN $addr");
          if ($ret) {
          next;
          }
        }
      }
      elsif($task =~ m/(update|force)/){
        foreach my $addr (@obsoletChn){
          CommandDefine (undef, "$fhemChnH{$defs{$addr}{DEF}}");
        }
      }
    }
}

sub HMCCU_evalDevDesc ($$)
{
my ($descH,$rpcH)  = @_;  # hash to device description
    my %FLAGSdev  = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x08 => "DontDelete"
          );
    my %DIRECTION  = (
           0 => "NONE"
          ,1 => "SENDER"
          ,2 => "RECEIVER"
          );
    my %RX_MODE = (
           0x01 => "ALWAYS"
          ,0x02 => "BURST"
          ,0x04 => "CONFIG"
          ,0x08 => "WAKEUP"
          ,0x10 => "LAZY_CONFIG"
          );
    my %FLAGSparam = (
           0x01 => "Visible"
          ,0x02 => "Internal"
          ,0x04 => "Transform"
          ,0x08 => "Service"
          ,0x10 => "Sticky"
          );
    my %OPERATIONS = (
           0x01 => "R"
          ,0x02 => "W"
          ,0x03 => "RW"
          ,0x04 => "E"
          ,0x05 => "RE"
          ,0x06 => "WE"
          ,0x07 => "RWE"
          );
     
     
    my $addr  = defined $descH->{ADDRESS}    ? $descH->{ADDRESS}     : $descH->{PARENT};
    return if (defined $HMCCU_EntData{$addr});
    my $idx   = defined $descH->{INDEX}      ? $descH->{INDEX}       : "dev";           # channel number
    my $model = defined $descH->{PARENT_TYPE}? $descH->{PARENT_TYPE} : $descH->{TYPE}  ;# identify model for channel and device
    my $chTyp = defined $descH->{INDEX}      ? $descH->{TYPE}        : "dev";           # if not channel then chTyp = dev
    my $entDataOnly = (defined $HMCCU_DevDef{$model} && defined $HMCCU_DevDef{$model}{$chTyp}) ? 1 : 0; # no need for model description - already available


    $HMCCU_EntData{$addr}{dev}{interface} = $rpcH->{NAME};# store RPC interface
    $HMCCU_EntData{$addr}{dev}{MODEL}     = $model;
    $HMCCU_EntData{$addr}{$idx}{CHTyp}    = $chTyp;
   
    $HMCCU_DevDef{$model}{$chTyp}{done} = 1;     # create hash entry
    my $DevDefH = $HMCCU_DevDef{$model}{$chTyp}; # create hash entry
   
    foreach my $k (keys %$descH){
      my $devLevel = defined $descH->{ADDRESS} ? "dev" : "chn";
      if ($entDataOnly || $k =~ m/(^ADDRESS|TYPE|VERSION|PARENT|INDEX)/ ){ ## ignore this
        next;
        }
      elsif ($k =~ m/(RF_ADDRESS|INTERFACE|FIRMWARE|AES|ROAMING)/){## todo: add this to dynamic data
        $HMCCU_EntData{$addr}{$idx}{$k} = $descH->{$k};
        }
      elsif($k eq "CHILDREN"){
        $DevDefH->{$k} = scalar @{$descH->{$k}};
        }
      elsif($k eq "PARAMSETS"){
        @{$DevDefH->{$k}} = @{$descH->{$k}};     
        }
      elsif($k eq "FLAGS"){
        foreach (keys %FLAGSdev){
          $DevDefH->{$k}{$FLAGSdev{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "RX_MODE"){
        foreach (keys %RX_MODE){
          $DevDefH->{$k}{$RX_MODE{$_}} = 1 if($_+0 & $descH->{$k}+0);
          }
        }
      elsif($k eq "DIRECTION"){
        $DevDefH->{$k} = $DIRECTION{$descH->{$k}};
        }
      else{
        $DevDefH->{$k} = $descH->{$k};
      }
    }
    $DevDefH->{LinkRole} = (!defined $DevDefH->{LINK_SOURCE_ROLES} || $DevDefH->{LINK_SOURCE_ROLES} ne "") ? "source"
                          :(!defined $DevDefH->{LINK_TARGET_ROLES} || $DevDefH->{LINK_TARGET_ROLES} ne "") ? "target"
                          :"none";
   
    return if ($entDataOnly); # only once required
    foreach my $k (@{$DevDefH->{PARAMSETS}}) { # foreach paramset
      my $res = HMCCURPCPROC_SendRequest ($rpcH,"getParamsetDescription", $addr.":".($idx eq "dev"?"":$idx),$k  );

      @{$DevDefH->{DPs}{$k}} = keys %$res; # store the list if datapoints

      foreach my $var (keys %$res){
        next if ($var =~ m/fault/);
        foreach my $varAttr (keys %{$res->{$var}}){
          if   ($varAttr =~ m/(ID)/){
            next;
            }
          elsif($varAttr eq "SPECIAL"){
            foreach my $x (@{$res->{$var}{$varAttr}}){
              foreach my $tp (keys %{$x}){
                $HMCCU_ParamDesc{$var}{$varAttr}{$tp} = $x->{$tp};
                }
              }
            }
          elsif($varAttr eq "VALUE_LIST"){
            @{$HMCCU_ParamDesc{$var}{$varAttr}} = @{$res->{$var}{$varAttr}};           
            }
          elsif($varAttr =~ m/LINK_.*ROLES/){
            @{$HMCCU_ParamDesc{$var}{$varAttr}} = split(" ",$res->{$var}{$varAttr});
            }
          elsif($varAttr eq "FLAGS"){
            foreach (keys %FLAGSparam){
              $HMCCU_ParamDesc{$var}{$varAttr}{$FLAGSparam{$_}} = 1 if($_+0 & $res->{$var}{$varAttr}+0);
              }
            }
          elsif($varAttr eq "OPERATIONS"){
            $HMCCU_ParamDesc{$var}{$varAttr} = $OPERATIONS{$res->{$var}{$varAttr}};
          }
          elsif($varAttr =~ m /(MIN|MAX|DEFAULT)/){
            if ($res->{$var}{TYPE} eq "ENUM"){
              $HMCCU_ParamDesc{$var}{MIN} = "0";
              $HMCCU_ParamDesc{$var}{MAX} = scalar(@{$res->{$var}{VALUE_LIST}});
              $HMCCU_ParamDesc{$var}{DEFAULT} = "-";
            }
            else{
              $HMCCU_ParamDesc{$var}{$varAttr} = $res->{$var}{$varAttr};
            }
          }
          else{
            $HMCCU_ParamDesc{$var}{$varAttr} = $res->{$var}{$varAttr};         
            }
          }
        }
      }
}

sub HMCCU_ccuNames ()
{
    my $hash = $defs{HMccu};
    my $update = 0;
    foreach(keys %HMCCU_EntData){
      if (!defined $HMCCU_EntData{$_}{ccuName}){
        $update = 1;
        last;
      }
    }
    return if(!$update); # do not update if the namelist is complete
my $response = HMCCU_HMScriptExt ($hash, "!GetDeviceList", undef, undef, undef);

return if ($response eq '' || $response =~ /^ERROR:.*/);

my @scrlines = split /[\n\r]+/,$response;
foreach my $hmdef (@scrlines) {
      my @hmdata = split /;/,$hmdef;
      next if (scalar ((@hmdata) == 0) || ($hmdata[0] !~ m/^[CD]/));
      my $addr = $hmdata[0] eq "C" ? $hmdata[1] : $hmdata[2];
      my $name = $hmdata[0] eq "C" ? $hmdata[2] : $hmdata[3];
      $HMCCU_EntData{$addr}{ccuName} = $name;
    }
}

sub HMCCU_params($)
{
my ($name)  = @_;  # address of the entity - i.e. the serial number
    my $addr = $defs{$name}{ccuaddr};
    return "$name is undefined" if(!defined $defs{$name}
                                 ||!defined $defs{$name}{ccuaddr});
    return "$name not found in CCU" if(!defined $HMCCU_EntData{$addr});
    my ($devAddr,$idx) = split(":",$addr);
    $idx = "dev" if (!defined $idx);
    my $rpcIf = $defs{$HMCCU_EntData{$devAddr}{dev}{interface}};
    return "RPC interface undefined for $addr" if (!defined $rpcIf || $rpcIf eq "");

    my $res="***  $name addr:$addr";
    $res .= "\ndev:$_  : ".$HMCCU_EntData{$devAddr}{dev}{$_} foreach (sort keys %{$HMCCU_EntData{$devAddr}{dev}});
    $res .= "\n    $_  : ".$HMCCU_EntData{$addr}{$idx}{$_}   foreach (sort keys %{$HMCCU_EntData{$addr}{$idx}});
    $res .= "\n----\n";

    my @addrList = ($addr);
    unshift @addrList,$devAddr if ($HMCCU_EntData{$addr}{$idx}{CHTyp} eq "MAINTENANCE");
    foreach my $dispAddr (@addrList){
      my ($dispSer,$dispIdx) = split(":",$dispAddr);
      $dispIdx = "dev" if (!defined $dispIdx);
      my $model = $HMCCU_EntData{$dispAddr}{dev}{MODEL};
      my $CHTyp = $HMCCU_EntData{$dispAddr}{$dispIdx}{CHTyp};
      my $role  = defined $HMCCU_DevDef{$model}{$CHTyp}{LinkRole} ? $HMCCU_DevDef{$model}{$CHTyp}{LinkRole} : "none";

      my %regH;
      foreach my $ps (@{$HMCCU_DevDef{$model}{$CHTyp}{PARAMSETS}}){
        my @peers;
        my @psList;
        if($ps eq "LINK"){ # with link we have to search each peer
          my $rl = HMCCURPCPROC_SendRequest ($rpcIf,"getLinks", $dispAddr, "");
          my $sStr = $role eq "source" ? "RECEIVER" : "SENDER";
          foreach my $hl (@{$rl}){
            push @peers, map{$hl->{$_}} grep /$sStr/,keys %$hl;
          }
          next if(scalar (@peers) == 0 || $role eq "none");
          @psList = @peers;
          $res .= " peerList:".join(",",@peers);
        }
        else{
          push @psList,$ps;
        }
        foreach my $psL (@psList){
          my $r = HMCCURPCPROC_SendRequest($rpcIf,"getParamset", $dispAddr, $psL);
          foreach my $k (sort keys %$r) {
            next if($k =~ m/(faultCode|faultString)/);
            my $val = $r->{$k};
            if (   defined $HMCCU_ParamDesc{$k}{VALUE_LIST}
               && scalar @{$HMCCU_ParamDesc{$k}{VALUE_LIST}} >= $val){
              $val = $HMCCU_ParamDesc{$k}{VALUE_LIST}[$val] ;
            }
            elsif($HMCCU_ParamDesc{$k}{TYPE} eq "BOOL"){
              $val = $val==0 ? "false" : "true";
            }
            elsif($HMCCU_ParamDesc{$k}{TYPE} eq "FLOAT"){
              $val =~ s/0*$//;
              $val =~ s/\.$//;
            }
            if($k =~m /^(SHORT|LONG)_(.*)/){
              $regH{$2}{$psL}{$1} = $val;
            }
            else{
              $res .= " $dispIdx   $psL: $k = $val\n";
            }
          }
        }
      }

      foreach my $reg (keys %regH){
        $res .= "\n ls: $reg:";
        foreach my $peer(sort keys %{$regH{$reg}}){
          foreach my $ls(sort keys %{$regH{$reg}{$peer}}){
            $res .= "\t$regH{$reg}{$peer}{$ls}";
          }
        }
      }
    }
    return $res;
}
sub HMCCU_paramDef($)
{
my ($name)  = @_;  # address of the entity - i.e. the serial number
    my $addr = $defs{$name}{ccuaddr};

    my $rpcIf = $defs{$HMCCU_EntData{$addr}{dev}{interface}};
    return "$name is undefined" if(!defined $defs{$name}
                                 ||!defined $defs{$name}{ccuaddr});
    return "$name not found in CCU" if(!defined $HMCCU_EntData{$addr});
    my ($devAddr,$idx) = split(":",$addr);
    $idx = "dev" if (!defined $idx);

    my $model = $HMCCU_EntData{$addr}{dev}{MODEL};
    my $chType = $HMCCU_EntData{$addr}{$idx}{CHTyp};
    my @chTypList = ($chType);
    unshift (@chTypList,"dev") if($idx == 0);
    Log 1,"General list:".join(",",@chTypList);
    my $res;
    foreach my $chTyp(@chTypList){
      $res .="***  $name addr:$devAddr No:$idx typ:$chTyp";
      foreach my $par (sort grep/DPs/,keys %{$HMCCU_DevDef{$model}{$chTyp}}){
        if (ref($HMCCU_DevDef{$model}{$chTyp}{$par}) eq 'ARRAY'){
          $res .= "\n   :$par  : ".join(",",@{$HMCCU_DevDef{$model}{$chTyp}{$par}});       
        }
        elsif(ref($HMCCU_DevDef{$model}{$chTyp}{$par}) eq 'HASH'){
          $res .= "\n   :$par  : ".join(",",keys %{$HMCCU_DevDef{$model}{$chTyp}{$par}});       
        }
        else{
          $res .= "\n   :$par  : ".$HMCCU_DevDef{$model}{$chTyp}{$par};
        }
      }
      foreach my $ifType (sort keys %{$HMCCU_DevDef{$model}{$chTyp}{DPs}}){
        $res .= "\nIF type: $ifType";
        my $resDp;
        foreach my $DP (sort @{$HMCCU_DevDef{$model}{$chTyp}{DPs}{$ifType}}){
          $resDp .= sprintf("\n %-23s :",$DP);
          my $parH = $HMCCU_ParamDesc{$DP};
          foreach my $DPattr("MIN","MAX","TYPE","UNIT","DEFAULT","OPERATIONS","FLAGS","VALUE_LIST"){#,"TAB_ORDER"
            if(!defined $parH->{$DPattr} || $parH->{$DPattr} eq ""){
              $resDp .= "-\t|";
            }
            elsif(ref($parH->{$DPattr}) eq 'ARRAY'){
              $resDp .= join(",",@{$parH->{$DPattr}})."\t|";
            }
            elsif(ref($parH->{$DPattr}) eq 'HASH'){
              $resDp .= join(",",keys%{$parH->{$DPattr}})."\t|";
            }         
            else{
              my $val = $parH->{$DPattr};
              $val =~ s/0*$//;
              $val =~ s/\.$//;
              $resDp .= "$val\t|";
            }         
          }
        }
        $res .= "\n                           ".join("\t|",("MIN","MAX","TYPE","UNIT","DEF","OPER","FLAGS","VALUE_LIST"))
               .$resDp
               ."\n                           ".join("\t|",("MIN","MAX","TYPE","UNIT","DEF","OPER","FLAGS","VALUE_LIST"));
      }
      $res .="\n";
    }
   
   
    $res .= "\n----\n";
    return $res;
}

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 03 Januar 2020, 17:45:15
Ich hab ein richtig schlechtes Gewissen, dass ich dieses Jahr noch nichts habe hören lassen. Ich habe auch etwas gebastelt. Allerdings mit etwas generischeren Ansätzen. Ich habe Deinen Code zwar nicht einfach übernommen, das Ergebnis ist für Dich hoffentlich auch brauchbar.

Ich befürchte, Du muss einiges an Deinem Code nochmal ändern. Sorry dafür vorab.

Ich checke spätestens Sonntag die neue Version ein. Diese enthält auf jeden Fall eine Abfrage aller Device und Paramset Descriptions inklusive Speicherung im Hash vom IO Device. Außerdem Funktionen, um auf diese Infos zuzugreifen. Ich poste dann hier eine Beschreibung der Funktionen.

Ich sehe es allerdings nicht so, dass alle Funktionen der CCU in FHEM abgebildet werden sollen. Es gibt Dinge, die sind in der CCU einfach und komfortabel. Warum sollte ich die in FHEM nachbauen (z.B. Verknüpfungen, die absolut genialen Heizungsgruppen, ...).

Ich halte es auch nicht für sinnvoll, für jeden Kanal eines Gerätes ein eigenes Device in FHEM zu haben. Das ist der totale Overkill.

So als Richtschnur: Dinge, die man nur einmal macht (Geräte anlernen, verknüpfen, ...) sollte man in der CCU machen. Alles andere, also Nutzung der Geräte, in FHEM. So ist es auch in anderen Smarthome Plattformen gelöst (ioBroker, OpenHab).
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 03 Januar 2020, 22:42:51
kein problem. ich habe nicht erwartet dass du den code so übernimmst. das ergebnis ist entscheident. das konzept als 2.
alle kanäle darzustellen ist kein overkill. funktioniert super in culhm. es hat schon seinen grund, dass eq3 es so organisiert hat. so lange du es nicht torpedierst bin ich dabei. es macht die struktur einfach,  homogen und kompatibel. für mich gibt es keinen anderen Weg.
direktverknüpfungen sind ein muss. ich habe auch schon alle ausgelesen und dargestellt.geht doch super einfach. ohne geht es für mich nicht. einrichten ist prio 2, aber Pflicht.
ich will immernoch von Konfiguration im ccu frontend unabhängig werden. bestmöglich.  bisher sieht es gut aus. 2 consolen ist nicht mein plan.

wichtig ist auch, dass die kommandos einfach, sehr einfach sind. besser automatich. in der frühen phase ist es bei mir normal, dass kommandos komplexe parameter haben. aber am ende, in der finalen version ist es inakzeptabel . beispiel ist dein kommando devicelist. es darf nur einen parameter haben. keine weiteren optionen. list listet alle entities. nicht dessen anzahl -was will ich damit? ich will bei der eingabe nicht die syntax nachsehen müssen. und ein createchn legt alle neuen kanäle an, update.. wie beschrieben.
ich sage es einmal so: die developer sind nerds und machen oft nerd frontends. wir müssen aber mehr "Steve Jobs". "max 1 button :) .
konfiguriere also alles automatisch und komplett. der nerd kann es dann verpfuschen. wenige können optimieren, wenn du gut warst. und es wird immer besser!

wieder einmal meine Sicht. 



Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: Ralli am 04 Januar 2020, 10:40:11
Kurze Zwischenfrage: kann die jeweilige RF-Adresse der Devices aus der CCU mit ausgelesen und in den Internals der fhem-Definitionen der Devices mit dargestellt werden?

Ich hatte in der Vergangenheit immer mal wieder einen Dauersender, den ich dann mit einem CUL und einem Skript ausfindig gemacht hatte. Die verursachende RF-Adresse musste ich dann immer in dezimal umrechnen und in der /etc/config/homematic.regadom suchen, um auf die SN des Devices zu kommen.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: marvin78 am 04 Januar 2020, 11:03:20
Zitat von: zap am 03 Januar 2020, 17:45:15


So als Richtschnur: Dinge, die man nur einmal macht (Geräte anlernen, verknüpfen, ...) sollte man in der CCU machen. Alles andere, also Nutzung der Geräte, in FHEM. So ist es auch in anderen Smarthome Plattformen gelöst (ioBroker, OpenHab).

Das heißt aber nicht, dass das der bessere Ansatz ist. Es ist im Gegenteil einer Bequemlichkeit der Entwickler geschuldet und nicht der Notwendigkeit oder Einfachheit.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 04 Januar 2020, 13:47:35
Die RF Adresse wird natürlich ausgelesen. Sie muss auch "abfragbar" sein. Ich würde sie entweder in meiner "Chan 0" darstellen oder über ein "get info" kommando zusammen mit sekundär Informationen ausgeben. Ich versuche immer, die Liste der Internals nicht endlos anwachsen zu lassen.
Dirk hat das letzte Wort zur offiziellen Implementierung

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: Ralli am 04 Januar 2020, 15:45:23
Alles klar. Wie, ist mir eigentlich egal, Hauptsache, ich kann gezielt nach der RF-Adresse suchen (am liebsten im Hex-Format) und bekomme das zugehörige Device mit der SN zurück.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 04 Januar 2020, 20:56:14
Hallo Dirk,
Die hmccu ist nicht korrekt angelegt.
Die ccu ist das übergeordnete device. Allerdings ist sie als bidcos device angelegt. Das macht schlussendlich probleme.

Defacto hat jedes rpc interface  ein (wichtiges) virtueles device mit 50 kanälen. Zumindest ist das für bidcos und hmip so.
Da es nun 2 (oder 4) devices gibt mit je 50 kanäle welche gepeert werden können macht es keinen sinn, dies als HMCCU zu instanziieren.
Die seriennummer  (Adresse) des bidcos darf nicht der ccu zugeordnet werden.
Kannst mdu das bereinigen?

Gruß Martin
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 05 Januar 2020, 17:50:48
Hallo Dirk,
ich habe die neue version nun eingespielt. Mir ist nicht klar, was jetzt alles funktionieren soll.
Vorab:
wenn ich über RPC ein getValue absetze bekomme ich als Antwort "0" und die Info, dass Parameter fehlen. Weit du, was hier fehlt?
{HMCCURPCPROC_SendRequest ($defs{d_rpc178046BidCos_RF},"setValue", "OEQ0693948:1","LEVEL","1.0")}
sollte mein device einschalten. was könnte das Problem sein?

Zu deinen Anpassungen - ich habe einmal die "gets" aus HMCCUCHN probiert. Bist du hier am Ziel oder noch am Umbauen?
config
Definition: get <name> config [device] [<filter-expr>]
- Filter sind wohl nicht notwendig. "device" würde ich entfernen. Der Kanal "0" sollte immer device und kanal 0 auf einmal anzeigen.
- ich bekomme AES = 0. Sollte "false" sein, da bool.
configdesc
Definition:perfekt
- bei Kanal "0" (MAINTENANCE) sollte immer das "Device" enthalten sein. Leider kommt da keine Antwort. Wenn keine Daten da sind sollte zumindest ein "none" zurück kommen.

configlist
was ist der Unterschied und warum braucht man 2 Kommandos?

alle Config
- werden die Daten aus dem cache von fhem gelesen? oder dem cache der ccu?
- Kann man den cacheupdate erzwingen? Fhem? CCU?
- Die konfigurationen der Links fehlen komplett. In definition und bei den Parametern
- die Peers sind nicht ersichtlich

deviceinfo
- im Channel brauche ich das nicht für alle Kanäle. Nur den einen Anzeigen
ZitatCHN MEQ0649984:0 las:0
  DPT {b} BidCos-RF.MEQ0649984:0.UNREACH = false [RE]
- Den ccu-namen hätte ich weg gelassen. Dafür den fhem namen eingetragen. Diesen nutzen wir hier
- "BidCos-RF.MEQ0649984:0." schlicht weglassen. Das ist doch schon klar.
- mir fehlt die eigentliche Beschreibung der Werte in der Form mit
ZitatMIN  |MAX    |TYPE   |UNIT   |DEF    |OPER   |FLAGS  |VALUE_LIST
INHIBIT                 :      |1      |BOOL   |-      |       |RWE    |Visible        |-      |
INSTALL_TEST            :      |1      |BOOL   |-      |       |RW     |Visible,Internal       |-      |
ON_TIME                 :0     |8580000        |FLOAT  |s      |0      |W      |Visible        |-      |
STATE                   :      |1      |BOOL   |-      |       |RWE    |Visible        |-      |
WORKING                 :      |1      |BOOL   |-      |       |RE     |Internal,Visible       |-      |
                           MIN  |MAX    |TYPE   |UNIT   |DEF    |OPER   |FLAGS  |VALUE_LIST

SHORT_OFF_TIME_MODE     :      |2      |ENUM   |-      |-      |RW     |Visible        |TIME_IS_ABSOLUTE,TIME_IS_MINIMAL       |
SHORT_ONDELAY_TIME      :0     |111600 |FLOAT  |s      |0      |RW     |Visible        |-      |
SHORT_ON_TIME           :0     |108000 |FLOAT  |s      |111600 |RW     |Visible        |-      |
SHORT_ON_TIME_MODE      :      |2      |ENUM   |-      |-      |RW     |Visible        |TIME_IS_ABSOLUTE,TIME_IS_MINIMAL       |
UI_HINT                 :-     |-      |STRING |-      |-      |RW     |Visible        |-      |


Generell ist dies dann aber in configdesc enthalten, also duplikate.

devstate
keine Reaktion bei mir. "none" oder "fail" ist das Mindeste.
Warum aber nicht gleich ein Update aller "VALUES" Parameter? Du sparst fast nix und kannst nur einen Parameter updaten.
Dann ist auch der Hinweis auf "STATE" egal. Alles einfacher, weniger einzustellen.
Das kommando kommt nicht in einem saparaten Fenser - warum? Nicht konsistent.

update
was ist mit "State" queried? Verstehe ich nicht.
Was bedeuted "nicht so genau aber schneller"?  Will jemand auch ungenaue updates?
Mir sind diese Kommentare komplett unverstädlich. Im code will ich es nicht nachlesen müssen. Allerdings muss ich wohl, will ich es verstehen.

Gruß Martin


Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 05 Januar 2020, 20:55:28
Ich schreibe morgen an dieser Stelle einiges zu den Änderungen in 4.4 in Bezug auf die internen Datenstrukturen sowie MEthoden, um auf sie zuzugreifen.

Was meinst Du mit neuer Version? Die Beta findest Du in contrib/HMCCU/FHEM.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 06 Januar 2020, 08:00:16
Guten Morgen Martin,

gestern habe ich die 4.4 Beta im contrib eingecheckt: https://forum.fhem.de/index.php/topic,107077.0.html

Intern hat sich einiges getan. Die wichtigsten Änderungen gibt es bei der Aktualisierung der CCU Geräte per RPC Schnittstellen.

Im Modul HMCCURPCPROC gibt es einen neuen Befehl get devicedesc. Damit wird die Device- sowie die Paramset-Description aller CCU Geräte, die der Schnittstelle des aktuellen HMCCURPCPROC Device zugeordnet sind, per RPC abgefragt und im Hash vom I/O Device gespeichert. Wenn der Befehl mit einer Geräteadresse aufgerufen wird, wird nur dieses Gerät inklusive seiner Kanäle synchronisiert.
Diese Synchronisation wird auch während der Initialisierung des HMCCURPCPROC Device ausgeführt. Ausnahme ist CUxD. Eine Synchronisation aller Geräte bewirkt hier, dass die CCU nicht mehr reagiert.
Intern verwendet der Befehl "get devicedesc" die Funktionen HMCCURPCPROC_GetDeviceDesc() und HMCCURPCPROC_GetParamsetDesc().

Wie gesagt, die Informationen werden dann im Hash vom I/O Device gespeichert:

Device Description: $hash->{hmccu}{device}{Interface}{Address}
Paramset Description: $hash->{hmccu}{model}{Type}{Fw_Ver}{Channel}{Paramset}

Platzhalter in kursiv. "Fw_Ver" ist eine Kombination aus Firmware Version und Version der Beschreibung. Das musste ich einführen, da sich die Paramsets je nach Firmware Version unterscheiden können. Die Device Description habe ich um einige Parameter ergänzt, die alle mit "_" beginnen. z.B. "_model" und "_fw_ver" als Einsprung in die "model" Datenstruktur.

Es gibt einige Funktionen in HMCCU, die den Zugriff auf diese Datenstrukturen ermöglichen:

HMCCU_AddDeviceDesc(): Fügt eine Device Description hinzu
HMCCU_GetDeviceDesc(): Liefert eine Hash-Referenz für die interne Device Description. Akzeptiert auch den Hash eines HMCCUCHN/HMCCUDEV Device als Parameter.
HMCCU_GetDeviceAddresses(): Liefert die Adressen aller Geräte und/oder Kanäle. Filterung möglich.

HMCCU_ExistsDeviceModel(): Prüft, ob ein Gerätetyp bereits bekannt ist.
HMCCU_AddDeviceModel(): Fügt einen Gerätetyp hinzu.
HMCCU_GetDeviceModel(): Liefert eine Hash-Referenz für die interne Gerätetyp Beschreibung.
HMCCU_GetClientDeviceModel(): Wie oben, allerdings genügt als Parameter der Hash eines HMCCUDEV oder HMCCUCHN Device.
HMCCU_FlagsToStr(): Wandelt einige Bitmasks in lesbare Springs um.

Zur Anwendung kommen die neuen Funktionen und Datenstrukturen im Modul HMCCUCHN bei den Befehlen get config, get configlist, get configdesc, get devicedesc. Diese Befehle verwenden soweit möglich die im I/O Device gespeicherten Informationen. Sie unterstützen außerdem alle Paramsets eines Device oder Kanals.
Alle anderen Befehle sowie HMCCUDEV habe ich noch nicht angefasst.

Zu Deinen anderen Fragen aus Deinem vorherigen Beitrag:

- Bei vielen RPC Requests muss der richtige Datentyp übergeben werden. Das könnte das Problem beim Setzen von LEVEL sein. Du übergibst einen String, erwartet wird aber FLOAT. Versuche es doch mal mit dem (leider schlecht dokumentierten) Befehl set rpcparameter, z.B. set xy rpcparameter VALUES LEVEL=100:DOUBLE.
- Die RPC Schnittstelle gibt bei BOOL Werten immer 0/1 zurück, auch bei den Events. Die ReGa hingegen interpretiert die RPC Werte und liefert dementsprechend true/false. Daher immer die Substitute Attribute bei vielen Devices, die das "normieren". Ich würde das auch nicht automatisieren. Es gibt User, die stehen auf "Raw Values".
- Die Ausgabe von Device Info kann ich noch anpassen
- get update: Ein "Value()" liefert immer den Wert, den die CCU gecacht hat. Daher entspricht er nicht unbedingt dem aktuellen, tatsächlichen Wert im Gerät. Ein State() hingegen zwingt die CCU, explizit beim Gerät den aktuellen Wert zu holen. Das dauert etwas länger. Ich würde mir darüber aber keine großen Gedanken machen, da alle Befehle zum Lesen von Datenpunkten wie "get update" sowie auch "get datapoint" oder "get devstate" eher selten bis nie genutzt werden, da die Werte von der CCU sowieso per RPC-Server automatisch aktualisiert werden. Wer möchte schon regelmäßig manuell oder per AT die Werte abfragen.
Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 06 Januar 2020, 12:30:10
Ah - das es in Contribute zu finden ist, ist mir entgangen.

HMCCURPCPROC finde ich nicht in contribute.
ZitatWenn der Befehl mit einer Geräteadresse aufgerufen wird
Warum Geräteadresse? alles (ALLES) sollte mit den FHEM Namen aufgerufen werden. alles andere ist "nerd" - kann sich keiner merken.

Ich habe die Dateien aus contribute eingepflegt. Nun habe ich kein RPC Interface mehr. Auch das Attribut der CCU rpcinterfaces ist nicht mehr verfügbar. Somit kann ich es erst einmal nicht testen. Was ist bei mir falsch?

ZitatWenn der Befehl mit einer Geräteadresse aufgerufen wird, wird nur dieses Gerät inklusive seiner Kanäle synchronisiert.
da ich nicht testen kann ist mir einiges unklar:
- evtl will ich die Spec nur "einsehen". Wie geht dies? Wenn FHEM es also "gecached" hat reicht dies zu 99,99% da es sich um die Spezifikation handelt. Diese ist gleich für alle Devices dieses Type und ändert sich nur bei einem SW-Update der CCU. 
=> nach einem Update der CCU kann ich einmalig alles lesen. Die Spec wird ja auch für alle anderen Operationen genutzt (enums,...) - muss also sowieso gelesen werden
==> warum also so komplex? das kannst du doch alles im Hintergrund ohne Kommando machen!

ZitatEine Synchronisation aller Geräte bewirkt hier, dass die CCU nicht mehr reagiert.
den Fall habe ich nicht. Hast du berücksichtigt, dass du nur einmal je "model-typ"  lesen musst?
Zitat
Paramset Description: $hash->{hmccu}{model}{Type}{Fw_Ver}{Channel}{Paramset}
Du hast auch die FW-Version berücksichtigt - sehr gut! hatte ich immer vernachlässigt.

Die Datenstruktur hört sich gut an. Allerdings kann ich es noch nicht testen.

ZitatDie RPC Schnittstelle gibt bei BOOL Werten immer 0/1 zurück ....,
das kannst (und solltest) du automatisch ersetzen, da du ja den Datentyp kennst. genauso wie Enums kannst du bool ersetzen. Der Anwender muss ich nicht kümmern.

ZitatIch würde das auch nicht automatisieren. Es gibt User, die stehen auf "Raw Values".
Da stimme ich nicht überein. Die Anwender können genauso auf true/false parsen. Nerds können das. Normale Anwender wollen es lesbar. Meine tiefe Überzeigung.

Zitatget update: Ein "Value()"...
das ist eine sehr wichtige Info. Die solltest du genauso in der Beschreibung verankern. Es beeinflusst den Duty-cycle,...
ZitatIch würde mir darüber aber keine großen Gedanken machen,
sehe ich anders. Durch deinen Kommentar erzwingst du, dass ich mir überlegen muss was das soll. Typisch reicht sicher der cache-wert.
Die Namensgebung halte ich für wenig intuitiv. Ein "cached" oder "CCU-cached" vs "forceRead" oder "readDevice" wären für mich deutlicher als Value/State. Das merke ich mich auf dauer noch nicht einmal.

Sobald ich infos habe, wie ich den contribute-code zum Laufen bekomme teste ich einmal



Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 06 Januar 2020, 12:52:40
noch etwas: die Defintition der "HMCCURPCPROC" entites funktioniert nicht mehr

Zitat2020.01.06 12:48:41.122 1: define d_rpc178046BidCos_RF HMCCURPCPROC http://192.168.178.46 BidCos-RF: Invalid port or interface BidCos-RF
2020.01.06 12:48:41.189 1: define d_rpc178046HmIP_RF HMCCURPCPROC http://192.168.178.46 HmIP-RF: Invalid port or interface HmIP-RF

Was ist zu tun? Was mache ich falsch?

Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: zap am 06 Januar 2020, 13:24:06
HMCCURPCPROC ist hier: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/HMCCU/FHEM/88_HMCCURPCPROC.pm.

Ich habe alle Module im contrib von meiner laufenden Entwicklungsumgebung kopiert. Das sollte sich zumindest starten lassen.

Der Befehl get devicedesc im RPC Device mit einer Geräteadresse aufzurufen, ist eher zum Testen gedacht. Normalerweise würde man alles syncen. Aber ich baue noch den FHEM Namen ein.

Die Daten werden ja im Hintergrund bzw. bei der Initialisierung der RPC Devices synchronisiert. Der Befehl get devicedesc im RPC Devices ist für die manuelle Synchronisierung gedacht. Dazu wird es mal ein Pendant im I/O Device geben, das dann für alle RPC-Devices die Synchronisation durchführt.

Das Problem, dass die CCU hängen bleibt, gibt es nur für das CUxD Interface. Aber das ist sowieso speziell, da binary RPC.

Zum Thema automatische Konvertierung 0/1 zu true/false: Manche bevorzugen true/false, manche aber auch on/off oder an/aus oder ... Wenn ich letzteren true/false vorschreibe, muss ich nicht lange auf die Beschwerden warten. Daher für jeden konfigurierbar. Ok, zumindest 0/1 true/false könnte man vereinheitlichen. Akzeptiert


Titel: Antw:HMCCUCHAN generischer Ansatz
Beitrag von: martinp876 am 07 Januar 2020, 20:54:18
Ok. Ich plane hoffentlich am Wochenende zu testen.
Die Beschwerden zu on\off kommen sowieso.
In fhem gibt es quasi-Standarte für readings wie batterie. 0\1 ist kein mir bekannter.
Auch wenn das etwas Aufwand kostet würde ich es implementieren. Der user sollte ein möglichst einheitliches Interface präsentiert bekommen.

Aber ich bin schon auf das neue modul gespannt. Das mit contribute hatte ich natürlich übersehen