ioBroker: Homematic CCU überwachen
Herzlich Willkommen bei IoT-Blog,
im heutigen Beitrag zeige ich dir eine Möglichkeit, wie du deine Homematic Zentrale mittels dem ioBroker überwachen kannst. Hierzu zeige ich ein Skript, welches die Parameter
- CPU-Frequenz
- Systemtemperatur
- Uptime
ausliest. Hierzu greifen wir auf die neu implementierte Messagebox des hm-rega Adapters zurück, indem wir unsere Skripte mittels der sendTo
Methode an den Adapter schicken. Neben den im Video gezeigten Parametern, könnt ihr auf diese Art auch andere Parameter auslesen oder gar Skripte komplett von der CCU nach ioBroker portieren. Dies hat meiner Meinung nach den Vorteil, dass man seine Skripte an einem zentralen Punkt warten kann.
Im Video erwähne ich, dass es Vorteile hat die Befehle mittels CuxD statt exec auszuführen, hier kannst du nähere Informationen dazu erhalten. Das Skript findest du hier.
Falls Ihr Fragen, Wünsche, Videoideen oder andere Anregungen habt, stellt diese gerne in Form eines Kommentars oder schreibt eine Mail an info@iot-blog.net.
Hi Moritz,
wie immer ein klasse Video, Danke für die investierte Zeit dafür!
Hab den Hinweis bezüglich Stress/Masterarbeit erst nach meiner Mail gelesen….daher warte ich in Ruhe ab und freue mich auf die Lösung wenn Sie kommt 😉
Grüße
Fabian
Danke für das Video und das Script!
Wenn man raspberrymatic am Tinkerboard laufen hat funktioniert die Abfrage der Temperatur mit vcgencmd nicht! Ich verwende da jetzt folgendes:
cat /sys/devices/virtual/thermal/thermal_zone0/temp | awk ‚// { printf $1/1000}‘
Grüße,
Sabine
Hey, super Arbeit, leider funktioniert es nicht so wie es soll bei mir.
Die CPU Frequenz bekomme ich nicht angezeigt und könnte man auch den benutzen RAM sowie den Duty Cycel auslesen und anzeigen? Wenn ja, kannst du mir da behilflich sein?
Grüße Nosec
Hi,
was genau funktioniert denn nicht? Der DutyCycle wird sogar von hm-Rega direkt geliefert, wenn Duty Cycle synchronisieren aktiviert ist in den Adaptereinstellungen. Dann ist dieser zu finden in den Objekten unter hm-Rega unter dem Kanal deiner CCU.
beste Grüße
Hey, habe jetzt nochmal in den iobroker reingeschaut, jetzt funktioniert die CPU Frequenzanzeige. Wie kann ich den benutzen Ram Bzw. den vorhandenen Ram auslesen?
Hey Moritz, kannst du mir bei meinem Problem nicht weiterhelfen ?
Hi, hatte dir auf deinen ursprünglichen Kommentar geantwortet. Du kannst grundsätzlich mittels der vorgestellten Variante alles in Datenpunkte schreiben, was du mittels Bash Kommandos auslesen kannst. Die Duty Cycle Abfrage ist wie erwähnt schon im Rega Adapter integriert. Leider weiß ich nicht was genau nicht funktioniert bei der CPU-Frequenz Abfrage.
Hey, ja die CPU Abfrage funktioniert hatte ich ja geschrieben. Irgendwie haben reden wir an einander vorbbei. 😀
Wenn ich den Befehl „df“ eingebe, bekomme ich die Informationen über den belegten, freien usw. Speicherplatz,
wie kann ich mir zb. nur den freien Speicherplatz anzeigen lassen? Sodass ich diesen Befehl dann in das IOBroker Script einbauen kann?
Sehe eigentlich zwei Optionen. Entweder du machst die komplette Vorverarbeitung in Bash oder du holst dir z. B. mittels
die Informationen und zerlegst sie dann in Javascript/Blockly so wie du sie benötigst. z. B. mittels Shell für die Partition
dev/mmcblk0p3
:df -h /dev/mmcblk0p3 | tail -1 | tr -s ' ' | cut -d' ' -f4
Hey, ich habe jetzt mal ein wenig rumprobiert in der Bash. Habe dein Script erweitert und der IOBroker zeigt mir 0,405mb an. In der Basch bekomme ich allerdings 12.285 angezeigt! was ist ihr falsch? und ist es wichtig welchen Cuxd Kanal man verwendet? du hast ja 2, 6 und 3 verwendet!
createState(‚javascript.0.ccu.sd_free‘, {
type: ’number‘,
write: false,
read: true,
unit: ‚mb‘
});
/* CuxD based */
const sd_freeScript = `
string command = „df -m /root | tail -1 | tr -s ‚ ‚ | cut -d‘ ‚ -f4 | awk ‚// { printf ($1 /1000)}'“;
dom.GetObject(„CUxD.CUX2801001:8.CMD_SETS“).State(command);
dom.GetObject(„CUxD.CUX2801001:8.CMD_QUERY_RET“).State (1);
WriteLine(dom.GetObject („CUxD.CUX2801001:8.CMD_RETS“).State());`;
sendTo(‚hm-rega.0‘, sd_freeScript, res => {
if (logging) log(JSON.stringify(res), ‚info‘);
if (!res.error) setState(‚javascript.0.ccu.sd_free‘, parseFloat(res.result), true);
else log(res.error, ‚warn‘);
});
Hey, Moritz so habe jetzt alles so weit hinbekommen, Was ich aber nicht verstehe, warum mir er mir im IObroker immer „null“ anzeigt bei diesem Befehl.
free | grep Mem | awk ‚{ printf( „%.1f\n“, $3/$2 *100) }‘
In der Bash funktioniert dieser Befehl einwandfrei. Ich habe alle Möglichkeiten was ich im Netz gefunden habe ausprobiert aber immer mit dem gleichen Ergebnis!
Top, am Besten lässt sich durch die „Skript testen“-Funktion oder mittels SSH auf der CCU testen, ob die Befehle grundsätzlich das tun, was sie sollen. Mit ‚in der Bash‘ meinst du auch direkt in der Bash der CCU? Der Befehl sollte so passen und funktioniert bei mir auf Raspberrymatic auch mit Bordmitteln. Zeig am Besten mal wie du den Befehl in ein Skript eingebunden hast, evtl macht eines der Anführungszeichen Probleme.
Hey, ja mit bash meine ich die Console direct auf der Raspimatic mit der ich mich mit putty verbinde.
/* CuxD based */
const memoryUsedScript = `
string command = „free | grep Mem | awk ‚{ printf( „%2.1f\n“, $3/$2 *100) }'“;
dom.GetObject(„CUxD.CUX2801001:8.CMD_SETS“).State(command);
dom.GetObject(„CUxD.CUX2801001:8.CMD_QUERY_RET“).State (1);
WriteLine(dom.GetObject („CUxD.CUX2801001:8.CMD_RETS“).State());`;
sendTo(‚hm-rega.0‘, memoryUsedScript, res => {
if (logging) log(JSON.stringify(res), ‚info‘);
if (!res.error) setState(‚javascript.0.ccu.memoryUsed‘, parseFloat(res.result), true);
else log(res.error, ‚warn‘);
});
Muss man für jeden Wert wo man abfragt eig. einen neuen/anderen Kanal verwenden bei dem Cuxd Gerät (CUxD.CUX2801001:xx)? Denn du hast wie es ausseht das willkürlich gemacht!?…1,2 und 6 hast du verwendet.
2
3
4
5
string command = "free | grep Mem | awk '{ printf( \"%2.1f\", $3/$2 *100) }'";
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State(command);
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State (1);
WriteLine(dom.GetObject ("CUxD.CUX2801001:1.CMD_RETS").State());`;
Wenn man die gleichen Anführungszeichen die zur Kennzeichnung des Strings verwendet werden, nochmal im String als Argument hat, werden diese als Ende des Strings interpretiert. Deshalb muss man diesen ‚escapen‘. Passiert in Javascript als auch in tcl mittels einem Backslash.
Glaube man muss nicht jedes mal einen neuen Kanal nehmen, solange es sich nicht überschneidet. Das virtuelle Gerät kann wohl nicht zeitgleich mehrere Befehle ausführen und für einen maximal flüssigen Ablauf würde es sich daher empfehlen unterschiedliche Kanäle zu nutzen, solange man welche frei hat. Bin mir allerdings nicht mehr 100 % sicher, vermute dies allerdings stark. 😉
Side Note:
WriteLine
spuckt am Ende immer noch eine neue Zeile mit aus, sprich im Logging wird es so aussehen:{"result":"17.5\r\n","error":null}
nutzt man nurWrite
, wird keine neue Zeile ausgegeben -> Resultat:{"result":"17.5","error":null}
. Dadurch, dass du am Ende sowieso nach float parsed ist es für den State allerdings egal.Ok, danke für die ausführlichen Infos. Leider funktioniert das bei mir in der Bash nicht, wenn der Befehl escapend wurde! Im IObroker logischerweise auch nicht 🙁
root@homematic-raspi:~# free | grep Mem | awk ‚{ printf( \“%2.1f\“, $3/$2 *100) }‘
awk: cmd. line:1: Unexpected token
In der Bash sollst du auch nicht escaped, das tcl Skript braucht den Escape. Also muss es nur im iobroker Skript abgeändert werden. So wie ich es oben eingefügt habe sollte es gehen, hatte es auch bei mir getestet.
Hey, bei mir funktioniert es leider nicht! Habe jetzt mal alle anderen Abfragen gelöscht und ur die RAM abfrage drin gelassen.
createState(‚javascript.0.ccu.memoryUsed‘, {
type: ’number‘,
write: false,
read: true,
unit: ‚%‘
});
createState(‚javascript.0.ccu.memoryFree‘, {
type: ’number‘,
write: false,
read: true,
unit: ‚%‘
});
// Update every 1 minutes
schedule(‚*/1 * * * *‘, () => {
const memoryUsedScript = `
string command = „free | grep Mem | awk ‚{ printf( \“%.1f\“, $3/$2 *100) }'“;
dom.GetObject(„CUxD.CUX2801001:1.CMD_SETS“).State(command);
dom.GetObject(„CUxD.CUX2801001:1.CMD_QUERY_RET“).State (1);
WriteLine(dom.GetObject („CUxD.CUX2801001:1.CMD_RETS“).State());`;
sendTo(‚hm-rega.0‘, memoryUsedScript, res => {
if (logging) log(JSON.stringify(res), ‚info‘);
if (!res.error) setState(‚javascript.0.ccu.memoryUsed‘, parseFloat(res.result), true);
else log(res.error, ‚warn‘);
});
/* CuxD based */
const memoryFreeScript = `
string command = „free | grep Mem | awk ‚{ printf( \“%.1f\“, $4/$2 * 100.0) }'“;
dom.GetObject(„CUxD.CUX2801001:9.CMD_SETS“).State(command);
dom.GetObject(„CUxD.CUX2801001:9.CMD_QUERY_RET“).State (1);
WriteLine(dom.GetObject („CUxD.CUX2801001:9.CMD_RETS“).State());`;
sendTo(‚hm-rega.0‘, memoryFreeScript, res => {
if (logging) log(JSON.stringify(res), ‚info‘);
if (!res.error) setState(‚javascript.0.ccu.memoryFree‘, parseFloat(res.result), true);
else log(res.error, ‚warn‘);
});
});
Magst du mir dein Skript Export einfach mal per Mail schicken, um anderweitige Fehler auszuschließen, dann kann ich die Tage mal schauen, was das noch sein könnte.
Moin Moritz,
kannst Du mir vielleicht sagen was in der CuxD eingestellt werden muss.
Gruß
Hi Ralf,
schau mal hier, insbesondere der Punkt ‚Installation EXEC-Gerät‘ ist vermutlich relevant für dich.
beste Grüße
Moritz
Hallo Moritz,
erst mal Danke aber ich bekomme das nicht hin mit der Einbindung
in den CuxD Adapter mit Geräten ist das kein Problem.
Gibt es da einen Trick ??
Gruß Ralf
Um was genau geht es denn? Um den CuxD Adapter oder um die Einrichtung von CuxD in der CCU? Der Adapter läuft über BIN-RPC Port 8701, dieser muss in der CCU Firewall auch freigegeben werden.
Hallo Moritz ,
ich habe auch das Problem mit:
cpuFrequency -> null MHz
systemTemperature -> null °C
uptime state -> null h
obwohl ich die Firewall freigegeben habe /Port 8701 /BIN RPC !
Keine Fehlermeldungen im log weder im Iobroker java noch im Iobroker Admin-log !
Aber im pivCCU3 (Vers.3.57.4) log habe ich folgende errors . :
Apr 3 15:20:00 piVccu3-webui local0.err ReGaHss: ERROR: ScriptRuntimeError: string command = „cat /proc/uptime | awk ‚// { printf $1/3600 }'“; dom.GetObject(„CUxD.CUX2801001:2.CMD_SETS“).State(command); dom.GetObject(„CUxD.CUX2801001:2.CMD_QUERY_RET“).State (1); WriteLine(dom.GetObject(„CUxD.CUX2801001:2.CMD_RETS“).State()); [ExecError():iseESPexec.cpp:12798]
Apr 3 15:20:00 piVccu3-webui local0.err ReGaHss: ERROR: ScriptRuntimeError: string command = „/usr/bin/vcgencmd measure_temp | awk ‚// { printf substr($1, length($1) -5, 4)}'“; dom.GetObject(„CUxD.CUX2801001:6.CMD_SETS“).State(command); dom.GetObject(„CUxD.CUX2801001:6.CMD_QUERY_RET“).State(1); WriteLine(dom.GetObject(„CUxD.CUX2801001:6.CMD_RETS“).State()); [ExecError():iseESPexec.cpp:12798]
Apr 3 15:20:00 piVccu3-webui local0.err ReGaHss: ERROR: ScriptRuntimeError: string command = „cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk ‚// {printf $1/1000}'“; dom.GetObject(„CUxD.CUX2801001:3.CMD_SETS“).State(command); dom.GetObject(„CUxD.CUX2801001:3.CMD_QUERY_RET“).State (1); WriteLine(dom.GetObject („CUxD.CUX2801001:3.CMD_RETS“).State()); [ExecError():iseESPexec.cpp:12798]
Moin,
also ich habe alle Ports auf offen stehen und und zusätzlich in der Portfreigabe die
8701 stehen sowie bei IP-Adressen die IP des ioBroker stehen alles andere steht auf Vollzugriff
bekomme aber immer
cpuFrequency -> null MHz
systemTemperature -> null °C
uptime state -> null h
muss ich im CuxD in Geräten irgend etwas ein stellen.
Gruß Ralf
Sorry, haben glaube etwas aneinander vorbei geredet. Also geht es doch um das Skript. 😉
Wird denn ein Fehler bei Ausführung des Skriptes geloggt (Admin -> Tab Log)?
Nein in der LOG macht es keinen Fehler
javascript.0 2020-03-06 18:30:23.097 info (2670) script.js.Geräte_Eckenreuth.Hardware.CCU3_Status: registered 0 subscriptions and 1 schedule
javascript.0 2020-03-06 18:30:23.091 info (2670) Start javascript script.js.Geräte_Eckenreuth.Hardware.CCU3_Status
javascript.0 2020-03-06 18:30:21.011 info (2670) Stop script script.js.Geräte_Eckenreuth.Hardware.CCU3_Status
so steht es im LOG und in schwarz.
Gruß Ralf
Hey, Ralf probiere mal diese Anleitung. Diese hatte ich vor längerem mal gemacht, um die CPU Temp der CCU in der Homematic angezeigt zu bekommen.
Und das Script von Moritz hatte auf Anhieb funktioniert!
https://technikkram.net/2017/10/raspberrymatic-ueberwachung-und-auswertung-der-raspberry-pi3-temperatur
Hallo,
wie bekomme ich die Uptime in : Tage, Stunden und Minuten ?
Danke
Sigi
Aktuell haben wir es ja in Stunden direkt ausgelesen. Eine Möglichkeit wäre direkt im JS-Skript. Den uptime State in Typ String umändern oder neuen erstellen, wenn beides gewünscht. Skript z. B. anpassen (quick n dirty – alternativ würde ich das Regaskript anpassen):
2
3
4
5
6
7
8
9
10
11
12
if (logging) log(JSON.stringify(res), 'info');
if (!res.error) {
const fullTime = parseFloat(res.result);
const days = parseInt(fullTime / 24);
const hours = parseInt(fullTime % 24);
const minutes = parseInt(((fullTime % 24) - parseInt(fullTime % 24)) * 60);
const timeString = `${days} days ${hours} hours ${minutes} minutes`;
setState('javascript.0.ccu.uptime', timeString, true);
} else log(res.error, 'warn');
});
Hallo Moritz,
bin aktuell auf dieses Script gestoßen und habe auch das Problem, dass keine Werte ankommen. Ich hab in Cuxd ein Systemgerät angelegt (Standard als Fernbedienung 19 Tasten ?). War das so richtig oder/und muss ich noch irgendetwas einstellen?
Gerätetyp muss „System“ sein und Funktion „exec“, wie hier beschrieben.