@apollon77 hat einen Artikel verfasst (c't 20-2021, Seiten 162 - 165).
NEWS

Best posts made by paul53
-
c't 20-2021
-
[Vorlage] Alias per Skript erzeugen
Im folgenden Skript wird ein Alias zu einem Datenpunkt mit dessen common-Eigenschaften erstellt. Bei gewollten Abweichungen von common-Eigenschaften des Alias zum Original muss man die zugehörigen // (Kommentar) entfernen und den gewünschten Wert zuweisen.
// Original-Datenpunkt const idOrigin = 'mqtt.0.switch.status'; // Optional: Status-Datenpunkt, wenn Kommando und Status getrennt. // Bei Nicht-Verwendung Leerstring '' zuweisen const idRead = ''; // Alias-Datenpunkt const idAlias = 'Pool.Pumpe.Schalter'; var typeAlias, read, write, nameAlias, role, desc, min, max, unit, states, custom, raum, gewerk; // Folgende kommentieren, wenn keine Änderung der Eigenschaft erforderlich nameAlias = 'Poolpumpe Ein'; desc = 'per Script erstellt'; // typeAlias = 'boolean'; // oder 'number' // read = "val < 0 ? -val : 0"; // Erkennung "Aus" --> false erfolgt automatisch // write = "val ? String(1) : String(0)"; // role = 'value'; // min = 0; // nur Zahlen // max = 100; // nur Zahlen // unit = '%'; // nur für Zahlen // states = {0: 'Aus', 1: 'Auto', 2: 'Ein'}; // Zahlen (Multistate) oder Logikwert (z.B. Aus/Ein) custom = {}; // verhindert doppelte Ausführung von history, ... // raum = 'EG_Flur'; // Groß-/Kleinschreibung in der ID beachten ! // gewerk = 'Licht'; // Groß-/Kleinschreibung in der ID beachten ! // Ab hier nichts ändern !! function createAlias(idDst, idSrc, idRd) { if(existsState(idDst)) log(idDst + ' schon vorhanden !', 'warn'); else { var obj = {}; obj.type = 'state'; obj.common = getObject(idSrc).common; obj.common.alias = {}; if(idRd) { obj.common.alias.id = {}; obj.common.alias.id.read = idRd; obj.common.alias.id.write = idSrc; obj.common.read = true; } else obj.common.alias.id = idSrc; if(typeAlias) obj.common.type = typeAlias; if(obj.common.read !== false && read) obj.common.alias.read = read; if(obj.common.write !== false && write) obj.common.alias.write = write; if(nameAlias) obj.common.name = nameAlias; if(role) obj.common.role = role; if(desc) obj.common.desc = desc; if(obj.common.type == 'number') { if(min !== undefined) obj.common.min = min; if(max !== undefined) obj.common.max = max; if(unit) obj.common.unit = unit; } else { if(obj.common.min !== undefined) delete obj.common.min; if(obj.common.max !== undefined) delete obj.common.max; if(obj.common.unit) delete obj.common.unit; } if(states) obj.common.states = states; if(custom && obj.common.custom) obj.common.custom = custom; obj.native = {}; setObject(idDst, obj, function() { if(idRd) setState(idRd, getState(idRd).val, true); else setState(idSrc, getState(idSrc).val, true); }); if(raum && existsObject('enum.rooms.' + raum)) { let obj = getObject('enum.rooms.' + raum) obj.common.members.push(idDst); setObject('enum.rooms.' + raum, obj); } if(gewerk && existsObject('enum.functions.' + gewerk)) { let obj = getObject('enum.functions.' + gewerk) obj.common.members.push(idDst); setObject('enum.functions.' + gewerk, obj); } } } createAlias('alias.0.' + idAlias, idOrigin, idRead);
Beispiele für Konvertierung (write);
write = "val ? 1 : 0"; // boolean --> binary write = "val ? 'On' : 'Off'"; // boolean --> string write = "val.toString()"; // number --> string dezimal write = "val.toFixed(2)"; // number --> string mit 2 Nachkommastellen
EDIT(20.12.2019): obj.native ergänzt.
EDIT(16.01.2020): Abfrage (Zeile 20) geändert
EDIT(06.02.2020): obj.common.custom ergänztEDIT(17.02.2020): Da man Raum und Gewerk in die Struktur der Alias-ID einbringen kann, sind enums für Raum und Gewerk oftmals nicht erforderlich. Für diejenigen, die den erzeugten Alias-Datenpunkt zu enum.rooms und/oder enum.functions hinzufügen wollen, wurde das Skript erweitert.
EDIT(21.04.2020): Erweiterung für getrennte Kommando- und Status-Datenpunkte ab js-controller 3.x.
EDIT(05.12.2020): Wenn Alias-Typ keine Zahl ist, werden min, max und unit gelöscht, falls vorhanden
EDIT(16.02.2021): Zeile 23 geändert von leerem Array in leeres Objekt
-
[Vorlage] Skript: Erstellen von User-Datenpunkten
// Datenpunkt unter 0_userdata.0 erstellen const idUser = 'EG_Kueche.Rollo.Schaltzeit2'; const commonUser = { // nicht benötigte Attribute auskommentieren type: 'number', read: true, write: true, name: 'Rollo Küche Schaltzeit 2', desc: 'Laufzeit Rollo', def: 60, min: 0, // nur bei Zahlen max: 200, // nur bei Zahlen unit: 's', // nur bei Zahlen // states: { // nur bei Zahlen, Logikwerten // 0: 'Aus', // 1: 'Auto', // 2: 'Ein' // }, role: 'level.timer' }; function createDp(id, common) { if(existsState(id)) log('Datenpunkt ' + id + ' existiert bereits !', 'warn'); else { var obj = {}; obj.type = 'state'; obj.common = common; obj.native = {}; setObject(id, obj, function (err) { if (err) log('Cannot write object: ' + err) else { var init = null; if(common.def === undefined) { if(common.type === 'number') init = 0; if(common.type === 'boolean') init = false; if(common.type === 'string') init = ''; } else init = common.def; setState(id, init, true); } }); } } createDp('0_userdata.0.' + idUser, commonUser);
EDIT: Abfrage geändert, ob Datenpunkt schon vorhanden ist.
-
[Vorlage] Wechselseitige Aktualisierung und Bedienung von Datenpunkten
In Fällen, in denen der Wert von einem Gerät auf ein anderes Gerät (und umgekehrt) übertragen werden soll, muss man ein endloses Hin- und Her vermeiden. Damit ein Triggern auf das setState() verhindert wird, kann im Trigger die Quelle (from) ausgewertet werden.
// Wechselseitige Aktualisierung von Datenpunkten const id1 = '...'; // Datenpunkt-ID vom Gerät 1 const id2 = '...'; // Datenpunkt-ID vom Gerät 2 const js = 'system.adapter.javascript.' + instance; on({id: id1, change: 'ne', fromNe: js}, function(dp) { setState(id2, dp.state.val); }); on({id: id2, change: 'ne', fromNe: js}, function(dp) { setState(id1, dp.state.val); });
In Blockly muss die aktuelle JS-Instanz fest eingetragen werden.
-
RE: [gelöst] Skript auf AXIOS/httpGet umbauen
@negalein sagte: request durch httpGet oder axios zu ersetzen.
Lass Zeile 10 weg und ersetze Zeilen 12, 13 durch
httpGet(url, (err, response) => { if(!err) { const body = response.data;
Die Funktion liest nicht nur das JSON ein, sondern wandelt es auch in ein Objekt.
-
RE: einfacher Timer, nach x Min Aus
@maddin77 sagte: wenn ich während den 30min den Schalter drücke ignoriere den Schalter erst wenn Zeit abgelaufen wieder Aktiv
-
RE: Variable einmal Pro Monat Protokollieren
@codierknecht sagte: Dann läuft der Kram 30x im Monat ohne etwas zu tun.
Das kann man im CRON eingrenzen. Es ist weniger aufwändig und funktioniert auch nach einem Skript-Neustart.
-
RE: braucht Pi4 8GB ein Gehäuse mit Lüfter?
@tt-tom sagte: wenn man die Kiste mal festhalten muss
Topflappen?
-
RE: [gelöst]Fenster Zählen mit Blockly
@MyzerAT Ganz schön kompliziert - Dein Ansatz.
Einfaches Prinzip (Beispiel mit 3 Fenstern):
Latest posts made by paul53
-
RE: Verzögerungszeit steuern
@oliver1972 sagte: Kann man das irgendwie in Minuten hinkriegen?
-
RE: [Gelöst] FoxESS Cloud Javascript Warnmeldungen
@torsten-g sagte: Problem gelöst
Mit Zahlen oder Strings?
-
RE: [gelöst] Liste/json erstellen und erweitern
@david-g sagte: was muss ich es wo konvertieren?
Wenn der Datenpunkt "Verlauf2" vom Typ "array" ist, muss (darf) nichts konvertiert werden.
Wenn der DP aber vom Typ "string" oder "json" ist, muss beim Einlesen und Schreiben konvertiert werden.
-
RE: [Gelöst] FoxESS Cloud Javascript Warnmeldungen
@torsten-g sagte: Das funktioniert leider nicht.
Ich hatte die erste Zeile nachträglich korrigiert. Hast du die Korrektur übernommen?
const datas = JSON.parse(res).result[0].datas;
Die Datenpunkte müssen vom Typ "number" sein.
@torsten-g sagte in FoxESS Cloud Javascript Warnmeldungen:
Object 0_userdata.0.FoxEss.PVPower is invalid: Default value has to be type "string" but received type "number"
Wenn du Strings verwenden möchtest, musst du auch common.def von 0 (Zahl) in "" (Leerstring) ändern.
-
RE: [Gelöst] FoxESS Cloud Javascript Warnmeldungen
@torsten-g sagte: Licht ans Fahrrad machen ?
Da es sich um Zahlenwerte handelt, ändere Zeilen 41 bis 47:
const datas = JSON.parse(res).result[0].datas; setState("0_userdata.0.FoxEss.PVPower", Math.round(datas[0].value * 1000) / 1000, true); setState("0_userdata.0.FoxEss.SOC", datas[2].value, true); setState("0_userdata.0.FoxEss.Load", Math.round(datas[3].value * 1000) / 1000, true);
-
RE: Lampe geht von alleine an
@michael-schmitt sagte: hier die Meldung
Hier ist ioBroker nicht beteiligt, denn sonst müsste vor der bestätigten eine unbestätigte Aktualisierung erscheinen.
Oder sind Kommando und Status verschiedene Datenpunkte?
Im Skript wird "level" gesteuert, es muss also auch dieser DP per Debug-Log überwacht werden. -
RE: Lampe geht von alleine an
@michael-schmitt sagte: Möglichkeit heraus zu finden, wer oder was in meinem System dafür verantwortlich ist ?
Debug-Log auf den Status-DP der Lampe:
-
RE: User-DP / Alias auf täglich geänderten DP "linken"
@topsurfer sagte: super, funzt.
Wenn du jede Minute einliest, wirst du vermutlich um 0:00 Uhr eine Warnung erhalten, wenn der Datenpunkt zu jedem Datum erst neu erstellt wird.
Werden die Datenpunkte am Monatsende wieder gelöscht? Falls nicht, gibt es das Problem nur im ersten Monat. -
RE: Datum umrechnen in Unix Millisekunden
@randyandy
Es genügt auch, Tag und Monat auszutauschen (US-Format): "05/25/2025 15:55:00"