HM_ReadServiceMessages findet keine HMIP Meldungen

Ich danke dir!

Hallo zusammen,

ich hole das Thema mal wieder hoch. :slight_smile:

Hat jemand eine CCU3 mit HMIP am Laufen und kann mit Symcon inzwischen die Service Meldungen auslesen?

Nutze folgendes.

https://www.symcon.de/service/dokumentation/modulreferenz/homematic/hm-readservicemessages/
Hat EQ3 hier wirklich seit 3 Jahren nix gemacht oder mache ich hier was falsch?

Habe in der CCU3 definitiv mit Absicht einen Low Batt Fehler, seit Tagen, Symcon sagt mir aber keine Service Meldungen vorhanden.

Genau so ist es.
Michael

Also mal den Support nerven. :see_no_evil: :man_facepalming:

Ich habe erst letztens ein vier Jahre altes Issue gefunden.

Aber da tut sich gar nichts🙁

Mich hat das Thema mit der fehlenden Unterstützung der Service-Messages die Tage mal wieder richtig angenervt und daher habe ich was gebaut.

Und zwar besteht das aus zwei Teilen

  1. eine Systemvariable auf der HM-Seite, die eine Liste der Servicemessages enthält und das dazugehörige Script
  2. auf der Seite von IPS ein Script, das diese Variable dekodiert und in meinem Fall in eine HTML-Box füllt

Programm auf HM-Seite

Programm auf HM-Seite

object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);
string svVarName = "Servicemeldungen-Liste";
object svObj = dom.GetObject(ID_SYSTEM_VARIABLES).Get(svVarName);
if (!svObj){
    svObj = dom.CreateObject(OT_VARDP);
    svObj.Name(svVarName);
    svObj.ValueType(ivtString);
    svObj.ValueSubType(istChar8859);
    svObj.DPInfo("Liste der aktuellen Servicemeldungen");
    svObj.ValueUnit("");
    svObj.State("");
    svObj.Internal(false);
    svObj.Visible(true);
    svObjects.Add(svObj.ID());
    dom.RTUpdate(true);
}
object svIDs = dom.GetObject(ID_SERVICES);
if (svIDs) {
    string svID;
    string result = "";
    foreach(svID, svIDs.EnumIDs()){
        object svObj = dom.GetObject(svID);
        if (svObj) {
            if (svObj.IsTypeOf(OT_ALARMDP) && (svObj.AlState() == asOncoming)) {
                var trigDP = dom.GetObject(svObj.AlTriggerDP());
                var ch = dom.GetObject(trigDP.Channel());
                var sdev = dom.GetObject(ch.Device());
                var sdesc = trigDP.AlDestMapDP().Name().StrValueByIndex(".", 2);
                integer created = svObj.AlOccurrenceTime().ToInteger();
                integer updated = svObj.LastTriggerTime().ToInteger();
                if (result <> "") {
                    result = result # ",";
                }
                result = result # "{\"address\":\"" # sdev.Address() # "\",\"name\":\"" # sdev.Name() # "\",\"error\":\"" # sdesc # "\",\"created\":" # created # ",\"updated\":" # updated # "}";
            }
        }
    }
    integer tstamp = system.Date("%F %X").ToTime().ToInteger();
    result = "{\"tstamp\":" # tstamp # ",\"messages\":[" # result # "]}";
    dom.GetObject(ID_SYSTEM_VARIABLES).Get(svVarName).State(result);
}

Die auslösende Systemvariable Servicemeldungen gibt es anscheinend immer in einer HM-Installation (ich nutze Raspberrymatic), ist aber u.U. als intern gekennzeichnet und wird daher nicht angezeigt.
Zum Test macht es Sinn, auch mal eine Servicemeldung zu erzwingen (zB ein Batteriefach öffnen => „Sabotage“)

auf der IPS-Seite muss [Modul] Homematic Extended von @Nall-chan installiert sein, um die Systemvariablen abzurufen.

Das Script Servicemeldungen auslesen sieht so aus

<?php

$src_varID = xxxxx; // HM-Systemvariable "Servicemeldungen-Liste"
$dst_varID = yyyyy; // Variable vom Typ "String" und dem Variablenprofil "~HTMLBox"

$sdata = GetValueString($src_varID);
$jdata = json_decode(utf8_encode($sdata), true);
if ($jdata == false) {
    echo 'sdata="' . $sdata . '", json_error=' . json_last_error_msg() . PHP_EOL;
}

$addr2id = [];
$ids = IPS_GetInstanceListByModuleID('{EE4A81C6-5C90-4DB7-AD2F-F6BBD521412E}');
foreach ($ids as $id) {
    $addr = explode(':', IPS_GetProperty($id, 'Address'));
    if (isset($addr[0]) == false) {
        continue;
    }
    if (IPS_GetObject($id)['ObjectIsHidden']) {
        continue;
    }
    $addr = $addr[0];
    if (isset($addr2id[$addr]) == false) {
        $addr2id[$addr] = $id;
    }
}

$map_error = [
    'CONFIG_PENDING'       => 'Konfigurationsdaten stehen zur Übertragung an',
    'LOWBAT'               => 'Batterieladezustand gering',
    'LOW_BAT'              => 'Batterieladezustand gering',
    'UNREACH'              => 'Gerätekommunikation aktuell gestört',
    'STICKY_UNREACH'       => 'Gerätekommunikation war gestört',
    'SABOTAGE'             => 'Sabotage',
    'DEVICE_IN_BOOTLOADER' => 'Gerät startet',
    'UPDATE_PENDING'       => 'Update verfuegbar',
];

$html = '';

$html .= '<style>' . PHP_EOL;
$html .= 'body { margin: 1; padding: 0; font-family: "Open Sans", sans-serif; font-size: 20px; }' . PHP_EOL;
$html .= 'table { border-collapse: collapse; border: 0px solid; margin: 0.5em;}' . PHP_EOL;
$html .= 'th, td { padding: 1; }' . PHP_EOL;
$html .= '#spalte_name { width: 300px; }' . PHP_EOL;
$html .= '#spalte_address { width: 150px; }' . PHP_EOL;
$html .= '#spalte_updated { width: 150px; }' . PHP_EOL;
$html .= '#spalte_error { width: 400px; }' . PHP_EOL;
$html .= '</style>' . PHP_EOL;

if (isset($jdata['messages']) && count($jdata['messages'])) {
    $html .= '<table>' . PHP_EOL;

    $html .= '<colgroup><col id="spalte_name"></colgroup>' . PHP_EOL;
    $html .= '<colgroup><col id="spalte_address"></colgroup>' . PHP_EOL;
    $html .= '<colgroup><col id="spalte_updated"></colgroup>' . PHP_EOL;
    $html .= '<colgroup><col id="spalte_error"></colgroup>' . PHP_EOL;

    $html .= '<tr>' . PHP_EOL;
    $html .= '<td>Gerätname</td>' . PHP_EOL;
    $html .= '<td>Seriennummer</td>' . PHP_EOL;
    $html .= '<td>letzte Änderung</td>' . PHP_EOL;
    $html .= '<td>Meldung</td>' . PHP_EOL;
    $html .= '</tr>' . PHP_EOL;

    foreach ($jdata['messages'] as $message) {
        $error = $message['error'];
        if (isset($map_error[$error])) {
            $error = $map_error[$error];
        }

        $addr = $message['address'];
        if (isset($addr2id[$addr])) {
            $name = IPS_GetLocation($addr2id[$addr]);
            $name = preg_replace('/ \(:[0-9]*\)$/', '', $name);
        } else {
            $name = $message['name'];
        }

        $updated = date('d.m.y H:i:s', $message['updated']);

        $html .= '<tr>' . PHP_EOL;
        $html .= '<td>' . $name . '</td>' . PHP_EOL;
        $html .= '<td>' . $addr . '</td>' . PHP_EOL;
        $html .= '<td>' . $updated . '</td>' . PHP_EOL;
        $html .= '<td>' . $error . '</td>' . PHP_EOL;
        $html .= '</tr>' . PHP_EOL;
    }
    $html .= '</tdata>' . PHP_EOL;
    $html .= '</table>' . PHP_EOL;
} else {
    $html .= 'Keine Servicemeldungen';
}

SetValueString($dst_varID, $html);

das Script sollte dann natürlich an die eigenen Bedürfnisse angepasst werden, insbesondere wie der Name im IPS gesucht wird; man kann auch den von der CCU in $message['name'] bereitgestellten Namen verwenden, das ist dann halt die Bezeichnung auf der CCU.

Es wird aufgerufen durch ein Ereignis durch Änderung der Variable Systemmeldungen-Liste

Das Modul zum Abrufe der Systemvariablen wird ja entweder zyklisch abgerufen (da muss man nix machen) oder getigert werden durch die CCU.
Da ich die Erklärung von @Nall-chan auch nicht 100% verstanden hatte, eine Hilfestellung für andere mit dem gleichen Problem

  1. virtueller Taser auf der CCU

kann von dem „Gerät“ HmIP-RCV-50 oder HM-RCV-50 sein - das ich das umbenannt habe in IPS-Trigger ist nur zur Übersichtlichkeit.

und mit einem Programme auf der CCU ausgelöst

Es müssen hier alle Systemvariablen eingebunden sein, bei denen eine direkte Aktualisierung wünschenswert ist.

Dazu passend wird dieses Gerät auf der IPS-Seite angelegt

und als Trigger im Modul eingetragen

Wie gesagt, ich bin HM-seitig auch nur mit Try&Error unterwegs …

3 „Gefällt mir“

Coole Lösung. Wollte da eigentlich auch etwas direkt im HM Extended Modul einbauen, aber imho kann die CCU3 ja jetzt über BidCos das auch direkt. Nur in Symcon fehlt es noch. @paresy
Michael

Wo hast du da etwas gefunden?

Ich bin noch dabei mein Modul etwas zu erweitern und habe dort dann Mal getServiceMessages an den HmIP BidCos gesendet und das bekommen:


Michael

Ich glaube, das ist nur die alte Dummy-Meldung. Oder hast du das Gerät tatsächlich?

Das kann ich gar nicht sagen… der Test war schon etwas her und ich habe viele Geräte abgelernt hier rumliegen :smiley:
Kann aber durchaus sein, dass es nur ein Dummy ist… wie fies :frowning:

Früher gab es aber immer die Meldung vom BidCos das getServiceMessages eine unbekannte Funktion ist :confused:

Moin,

diejenigen Anwender, die z. B. piVCCU einsetzen und die Variable sichtbar machen wollen, finden hier Systemvariable manuell setzen - Seite 3 - HomeMatic-Forum / FHZ-Forum dazu die notwendigen Informationen.

Gruß
Hans

In der Tat. Da hat sich seit 5 Jahren nichts dran geändert. Ich glaube, die packen es nicht (an).

Burkhard

@Nall-chan
Gibt es hier inzwischen was neues? Also die Möglichkeit die IP LowBats trotzdem in der Meldung zu bekommen?

Also kann man Service-Messages von HM-IP-Geräten nicht auslesen? Ich hab bei mir gerade nur 2 ohne Batterie im Einsatz deswegen ist es mir nicht aufgefallen… gibts da keinen Workaround oder Alternativ-Weg?

Genau, Homematic IP stellt die leider nicht zur Verfügung.

ist der Weg, den ich hier beschrieben hatte, unvollständig?

Mal abgesehen davon, holte ich mit die Information über Batteriezustand eh direkt aus den Variablen der HM/HmIP-Geräte (typischerweise in Kanal 0)

Sorry, deinen Weg hatte ich übersehen. Er ist komplex, führt aber bestimmt zum Ziel.

Hi, ich hatte es auch übersehen… Sorry… Mein Workaround ist jetzt die xml-api in der CCu3 aber die muss ich pollen… dein Weg geht aktiv bei einer neuen Service-Message?

kein Problem.

ja. Der Ablauf ist folgender:

  • wenn sich etwas an der Service-Messages ändert, wird ein CCU-interner Zähler geändert (das ist Standard)
  • dessen Änderung löst ein Script auf der CCU aus, das die Variable mit den Servicemessages auf der CCU neu schreibt
  • diese Änderung löst auch (mit einem Delay von 1s) aus, das der virtuelle Taster gesetzt wird.
  • die Statusänderung des virtuellen Tasters wird auf dem normalen Weg ins IPS übertragen
  • dieser Datenpunkt dient als Trigger für das HomematicExtended-Modul von @Nall-chan.
  • die oben gefüllte Variable wird durch dieses Modul zum IPS geholt und dort in eine Variablen repliziert.
  • diese Variable im IPS löst dann per Ereignis ein Script aus, das alles weitere macht.
    Ausser dem o.g. Delay von 1s (damit sich dort intern nichts überholt), läuft alles in „RealTime“

Ich habe in der CCU einige weitere Variablen (Anzahl der Objekte, Server-Status der CCU, …), die alle bei Änderungen die Änderung der o.g. virtuellen Taste triggern und damit die Aktualisierung im IPS