Vitoconnect - Verbesserte Version

Begonnen von stefanru, 14 Dezember 2024, 23:32:17

Vorheriges Thema - Nächstes Thema

stefanru

Hi BetaUser,

oh wow das sind jetzt sehr spezifische Fragen.
Kannst du da ein Beispiel machen.

Ja ich achte auf das isExecutable Flag, wenn etwas nicht schaltbar ist wird es keinen Setter dafür geben.

Man muss auch sagen die API ist da total wild und ganz generisch geht es nicht.
Teilweise kommt es auf Reihenfolgen an die ja im JSON eigentlich nicht gegeben sind dann ist es uneinheitlich bei setActive und activate usw.
Das war ein Riesen Krampf, aber ich habe versucht es so generisch wie möglich hin zu bekommen, aber bei dem schlechten API Design gibt es ein paar Workarounds damit es überhaupt ging.

Ich versuche gern dir die Fragen im Detail zu erklären wenn du mir genau sagst was du wissen willst.
Was ist den depricated markiert?

Gruß,
Stefan

Beta-User

Zitat von: stefanru am 08 Mai 2025, 22:06:58oh wow das sind jetzt sehr spezifische Fragen.
Sorry for that :)

Habe gestern dann auch im Thread noch ein wenig rückwärts gelesen und gesehen, dass es dir v.a. darum geht, an die Infos zu kommen, weniger um's Steuern.

Zitat von: stefanru am 08 Mai 2025, 22:06:58Was ist den depricated markiert?
Einer von (bei mir) 6 Einträgen:
{
      "feature": "heating.circuits.0.operating.programs.noDemand",
      "gatewayId": "#gwid#",
      "deviceId": "0",
      "timestamp": "2025-05-09T04:28:24.746Z",
      "isEnabled": false,
      "isReady": true,
      "apiVersion": 1,
      "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/heating.circuits.0.operating.programs.noDemand",
      "properties": {},
      "commands": {},
      "deprecated": {
        "removalDate": "2024-09-15",
        "info": "replaced by heating.circuits.N.operating.programs.reducedEnergySaving"
      }
    },

Zitat von: stefanru am 08 Mai 2025, 22:06:58ich habe versucht es so generisch wie möglich hin zu bekommen, aber bei dem schlechten API Design gibt es ein paar Workarounds damit es überhaupt ging.
Ja, das sieht einigermaßen unübersichtlich aus, und wie man an "deprecated" erkennen kann, scheint auch einiges im Umbau zu sein, was ggf. einige "Uneinheitlichkeiten" erklären könnte.

Na ja, wir werden kaum Einfluss haben, wie es in der API künftig umgesetzt werden wird, sondern nur versuchen, "gute" und möglichst generische Lösungen zu finden, um das in FHEM (einigermaßen) sauber abzubilden.
ZitatKannst du da ein Beispiel machen.
Hier mal zwei Varianten:
{
      "feature": "heating.dhw.oneTimeCharge",
      "gatewayId": "#gwid#",
      "deviceId": "0",
      "timestamp": "2025-05-08T21:41:50.535Z",
      "isEnabled": true,
      "isReady": true,
      "apiVersion": 1,
      "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/heating.dhw.oneTimeCharge",
      "properties": {
        "active": {
          "type": "boolean",
          "value": false
        }
      },
      "commands": {
        "activate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/heating.dhw.oneTimeCharge/commands/activate",
          "name": "activate",
          "isExecutable": true,
          "params": {}
        },
        "deactivate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/heating.dhw.oneTimeCharge/commands/deactivate",
          "name": "deactivate",
          "isExecutable": true,
          "params": {}
        },
        "setActive": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/heating.dhw.oneTimeCharge/commands/setActive",
          "name": "setActive",
          "isExecutable": true,
          "params": {
            "active": {
              "type": "boolean",
              "required": true,
              "constraints": {}
            }
          }
        }
      }
    },
   
    {
      "feature": "device.time.daylightSaving",
      "gatewayId": "#gwid#",
      "deviceId": "0",
      "timestamp": "2025-05-08T21:41:50.535Z",
      "isEnabled": true,
      "isReady": true,
      "apiVersion": 1,
      "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/device.time.daylightSaving",
      "properties": {
        "active": {
          "type": "boolean",
          "value": true
        },
        "begin": {
          "type": "string",
          "value": "25-03"
        },
        "end": {
          "type": "string",
          "value": "25-10"
        }
      },
      "commands": {
        "activate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/device.time.daylightSaving/commands/activate",
          "name": "activate",
          "isExecutable": true,
          "params": {
            "begin": {
              "type": "string",
              "required": true,
              "constraints": {
                "regEx": "^[\\d]{2}-[\\d]{2}$"
              }
            },
            "end": {
              "type": "string",
              "required": true,
              "constraints": {
                "regEx": "^[\\d]{2}-[\\d]{2}$"
              }
            }
          }
        },
        "deactivate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/#installation#/gateways/#gwid#/devices/0/features/device.time.daylightSaving/commands/deactivate",
          "name": "deactivate",
          "isExecutable": true,
          "params": {}
        }
      }
    },

Das mit "oneTimeCharge" ergibt dann drei set-Kommandos, wobei in letzterem die "sinnvolle" Auswahl (on/off bzw. 0/1) "fehlt".
heating.dhw.oneTimeCharge.activate:noArg
heating.dhw.oneTimeCharge.deactivate:noArg
heating.dhw.oneTimeCharge.active
Als Reading taucht dann (m.E. korrekterweise) nur "heating.dhw.oneTimeCharge.active" auf.

Vermutlich sollten wir in den properties diesen Teil
"properties": {
        "active": {
          "type": "boolean",
anders auswerten und dann (tendenziell) die "activate"/"deactivate"-Teile in der setFn anders ergänzen als bisher bzw. mal schauen, was Roger dazu gebastelt hatte. Das sollte auch irgendwie generisch(er) gehen...

Vermutlich schaue ich mir das bei Gelegenheit mal an, aber die nächsten paar Tage wird das eher nichts.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Hi Beta-User,
danke!

Jetzt verstehe ich.
Also die deprecated gab es bei mir noch nicht.
Die könnte man ja auch wegfiltern, wie auch mit dem isExecutable.
Oder man lässt sie einfach bis sie dann entfernt werden?

Na mir ging es erst ums Auslesen und mappen.
Als ich dann für mich auf RawReadings ging habe ich aber auch das setzen generisch umgesetzt.

Heißt an deinem Beispiel, dass mein Coding dynamisch "heating.dhw.oneTimeCharge.active" als reading erkennt.
Daraus werden generisch 2 Setter erzeugt:
heating.dhw.oneTimeCharge.activate:noArg
heating.dhw.oneTimeCharge.deactivate:noArg
Diese funktionieren auch.

Und halt auch wie in der API beschrieben noch einen dritten heating.dhw.oneTimeCharge/commands/setActive.
Der wird im DropDown als heating.dhw.oneTimeCharge.active 0/1 angezeigt.
Also mein Coding bildet hier die API ab, alle 3 Setter sind vorhanden.

Der 3te führt aber zu:
  "details": "The parameter active=\"1\" does not meet the constraints {\"type\":\"boolean\"}: Value '1' should be a boolean."
Da sollte ich wirklich im Coding auf das boolean achten und true und false reingeben.

Dann wäre es aber ok, oder?

Gruß,
Stefan

Beta-User

Zitat von: stefanru am 09 Mai 2025, 10:48:44Der wird im DropDown als heating.dhw.oneTimeCharge.active 0/1 angezeigt.
Nope. Da kommt (im Moment) die 0 (=Reading-Wert) als Vorgabe für ein Freitextfeld.

Zitat von: stefanru am 09 Mai 2025, 10:48:44Dann wäre es aber ok, oder?
Hmmm, also:
M.E. sind 3 setter nicht optimal, auch wenn 2 davon ootb funktionieren.

Den "eigentlich korrekten" setter (der mit dem Reading-Wert verknüpft ist) zu reparieren (auch hinsichtlich der 0/1-Vorgabe), ist imo "nur" das Minimal-Ziel.

(Die anderen beiden setter in den Kindern wegzufiltern, ist dagegen kein Problem, aber imo eben unnötig, wenn es die schon im "Server" nicht mehr gibt.)

Vom Vorgehen her würde ich dazu tendieren, aus dem einen setter die "activate" bzw. "deactivate"-Variante abzuleiten und das dann für die URL-Generierung zu verwenden.
Sonderlocke: Ja, aber eben beschränkt auf "boolean", und soweit in meinen JSON erkennbar auch einheitlich und generalisierbar umsetzbar.

Nachvollziehbar?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Ok, ja nachvollziehbar.

Zur Zeit zeigt dieser Setter den aktuellen zustand an in einem Freitextfeld
Also bei mir heating.dhw.oneTimeCharge.active 0.

Man müsste den Setter also auf Boolean umstellen und invertieren.
Also so dass man heating.dhw.oneTimeCharge.active true setzen würde.
Immer passend zum aktuellen Zustand.

Richtig?

Gruß,
Stefan

Beta-User

Zitat von: stefanru am 09 Mai 2025, 12:17:20Man müsste den Setter also auf Boolean umstellen und invertieren.
Dass der aktuell eingestellte Wert als Vorgabe eingestellt ist, ist m.E. ok, Invertieren braucht (und sollte!) man dagegen nicht. Nur sollte dann eben die Auswahl auf das "passende Paar" beschränkt werden (statt Freitext). Da die API für bool 0 und 1 verwendet/zurückmeldet, wäre es eben das.
FHEM-typischer wäre on/off, aber wenn schon denn schon könnte man für set-Befehle auch eine Logik implementieren, die mit allen drei Werten (on=true=1) klar käme und (?) das dann in (z.B.) "heating.dhw.oneTimeCharge.activate" bzw. "heating.dhw.oneTimeCharge.deactivate" umsetzt.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

#261
Ok,
jetzt reden wir aber etwas aneinander vorbei.
Bisher haben bei Raw readings die Setter im UI die Namen der Readings z.B. heating.circuits.0.heating.curve.shift.
Umgesetzt wird das dann wenn der Set Befehl gesendet wird.

Also wenn wir das für die Booleans so auch machen wollen müsste man doch:
heating.dhw.oneTimeCharge.activate:noArg
heating.dhw.oneTimeCharge.deactivate:noArg
entfernen und nur:
heating.dhw.oneTimeCharge.active [boolean]
nehmen.
Der beim senden dann
heating.dhw.oneTimeCharge/commands/setActiv [boolean] wird.

Also alles in allem scheine ich boolean nicht richtig zu beachten.
Im Coding habe ich:
                        } elsif ($param->{'type'} eq 'boolean') {
                            $val .= "$readingName ";

Ich kann mal schauen warum das nicht klappt und was ich machen muss.
Dann würden diese Setter auch gehen.
Die anderen beiden rausfiltern kann man dann noch machen.
Eventuell nur in einem Child?

Gruß,
Stefan


P.S.:
Ist ja lustig.
Bei mir sieht das API JSON mitlerweile anders aus und es gibt kein setActive mehr:
    {
      "feature": "heating.dhw.oneTimeCharge",
      "gatewayId": "7736172146035226",
      "deviceId": "0",
      "timestamp": "2025-03-07T12:06:31.802Z",
      "isEnabled": true,
      "isReady": true,
      "apiVersion": 1,
      "uri": "https://api.viessmann.com/iot/v2/features/installations/2772216/gateways/7736172146035226/devices/0/features/heating.dhw.oneTimeCharge",
      "properties": {
        "active": {
          "type": "boolean",
          "value": false
        }
      },
      "commands": {
        "activate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/2772216/gateways/7736172146035226/devices/0/features/heating.dhw.oneTimeCharge/commands/activate",
          "name": "activate",
          "isExecutable": true,
          "params": {}
        },
        "deactivate": {
          "uri": "https://api.viessmann.com/iot/v2/features/installations/2772216/gateways/7736172146035226/devices/0/features/heating.dhw.oneTimeCharge/commands/deactivate",
          "name": "deactivate",
          "isExecutable": true,
          "params": {}
        }
      }
    },

Somit wäre meine Idee von oben hinfällig und man müsste eigentlich nur den unnötigen Setter ausblenden.
Das JSON neu einlesen hat den Setter setActive aber nicht verschwinden lassen.
Da muss ich mal drüber nachdenken warum er den noch anzeigt.

Gruß,
Stefan

Beta-User

#262
Zitat von: stefanru am 09 Mai 2025, 12:37:04Also wenn wir das für die Booleans so auch machen wollen müsste man doch:
heating.dhw.oneTimeCharge.activate:noArg
heating.dhw.oneTimeCharge.deactivate:noArg
entfernen und nur:
heating.dhw.oneTimeCharge.active [boolean]
nehmen.
Korrekt. Das war der Vorschlag.


Zitat von: stefanru am 09 Mai 2025, 12:37:04Der beim senden dann
heating.dhw.oneTimeCharge/commands/setActiv [boolean] wird.
Da das "setActive" anscheinend nicht immer klappt, wenn wir es mit boolean zu tun haben, müßte man m.E. entweder erst schauen, ob es das gibt, und/oder gleich die anderen "topics" verwenden.

EDIT: qed mit deinem JSON-update...

Was das Rausfiltern angeht: bei den Kindern geht das schon jetzt. Imo ist es aber verwirrend, wenn man für ein und denselben Zweck 3 set-Optionen hat (von denen nur 2 einen Effekt haben können).
Von daher würde ich dafür votieren, das "FHEM-ish" zu gestalten und beim Prinzip "das Reading soll geändert werden" bleiben und auch im Hauptdevice ausschließlich die eine set-Option anbieten. Dann muss man übrigens hinterher bei den Kindern auch nichts mehr filtern ;) .

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Ok, ja verstehe ich.
Da es bei mir im JSON gar kein setActive mehr gibt müsste ich erstmal nachschauen warum es den Setter noch gibt.
Das verstehe ich gerade nicht.
Sollte doch hierüber gar nicht reinkommen:
 if (exists $item->{commands}) {

Gruß,
Stefan

Beta-User

Zitat von: stefanru am 09 Mai 2025, 12:37:04Das JSON neu einlesen hat den Setter setActive aber nicht verschwinden lassen.
Da muss ich mal drüber nachdenken warum er den noch anzeigt.
Hmmm, unabhängig von allem:

In meinem Code ist das mit den set-Befehlen noch etwas statischer, das wird im Prinzip nur einmalig zum define-Zeitpunkt ermittelt (bzw. wenn das JSON da ist), und bei den Kindern dann nochmal, wenn das mapping geändert wird.
Wenn sich das ändern kann, ist das nicht so lustig, allerdings hatte ich bisher keine offensichtlichen Probleme (aber auch nicht viel gemacht). Ggf. müssen wir einen timer einbauen, der das zumindest hin und wieder erneuert...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Ja so wie ich das jetzt sehe schrauben sie an dem JSON gerade rum.
Es habe sich eindeutig dinge geändert.
Bei mir sollten die Setter bei jedem Einlesen angepasst werden.

Habe gerade in einem neuen Device logReponceOnce gemacht und der Setter wurde erzeugt.
Beim nachschauen im JSON ist er jetzt auch wieder vorhanden in der API???

Ich denke das müssen wir mal beobachten, vielleicht ist da gerade nur viel im Gange.
Habe da etwas im Viessmann Forum gelesen.

Lange Rede kurzer Sinn:
Ja das API scheint sich zu ändern, damit sollte man umgehen können.
Zur Zeit erstelle ich die Setter dynamisch anhand des JSON bei jeder Response.
Es wäre aber auch ok die Änderungen per Setter neu einzulesen.
Wäre eventuell auch konsistenter und man weiß wann sich etwas ändern kann und es fehlen nicht auf einmal Setter und man weiß nicht warum.

Gruß,
Stefan

Beta-User

Vielleicht noch zur Klarstellung zu meinem Code: Auch da werden die set-Optionen jedes Mal neu erstellt, aber es wird der "choose one of"-String (als  Antwort auf "getAllSets()") zwischengespeichert bzw. nur am Ende neu erstellt, wenn ein unbekanntes Kommando versucht wird.
Damit soll verhindert werden, dass jedes Mal (wenn man die ganzen Log3-Answeisungen dazu nimmt) imo aufwändig der String zusammengebastelt wird, nur weil z.B. FHEMWEB wissen will, was im Frontend anzuzeigen ist...

"Echte" und nach dem jeweils aktuellen JSON zulässige set-Anweisungen sollten aber eigentlich immer funktionieren, aber ehrlich gesagt bin ich da im Moment auch noch nicht so tief drin, wie das im Details funktioniert O:-) .

Bei den gemappten Kindern ist das allerdings anders, weil da getAllSets() verwendet wird um rauszufinden, was "Server" kann.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Ja bin bei dir, das macht schon Sinn die Setter nicht immer wieder neu zu erstellen.
Hatte das beim Debuggen meines Codes auch beobachtet.
Wusste aber als Neuling nicht wie man das behebt und hab mich erstmal auf die Funktionalität konzentriert.

Also bin völlig bei dir das zu Puffern, macht Sinn!

Gruß,
Stefan

Beta-User

Kurze Zwischeninfo - habe hier mal einen Post dazu aufgemacht, wie man das mit den "Kindern" ggf. sonst noch lösen könnte: https://forum.fhem.de/index.php?topic=141647.0

Im Moment tendiere ich dazu, den Teil abzutrennen und vitoconnect selbst als (optionales!) IODevice im Sinne des 2-stufigen Modulkonzepts zu modifizieren. (Weitere Info gleich im anderen Thread).
Meinungen dazu?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

stefanru

Ok, super, danke für das Update.
Ich folge der Diskussion mal.
Klingt interessant.
Ich habe leider hier noch ein weiteres Problem bei mir persönlich und kann gerade nicht viel mithelfen.
Ich lese auf jeden fall mit und hoffe auch in einiger zeit wieder mit testen und wenn nötig auch entwickeln zu können.

Viele Grüße,
Stefan