NEWS
Zahl aus JS schafft es nicht in die MySQL-DB
-
Wenn ich mit HomematicIP einen Wert (Beispiel Luftfeuchte) in den Objektbaum schreibe, dann sieht das SO aus:
{ "type": "state", "common": { "name": "humidity", "type": "number", "role": "value.humidity", "unit": "%", "read": true, "write": false, "custom": { "sql.0": { "enabled": true, "storageType": "", "counter": false, "aliasId": "aH_Kueche", "debounceTime": 1000, "blockTime": 1000, "changesOnly": true, "changesRelogInterval": 3600, "changesMinDelta": 0, "ignoreBelowNumber": "", "disableSkippedValueLogging": true, "retention": 63072000, "customRetentionDuration": 365, "maxLength": 0, "enableDebugLogs": false, "debounce": 1000
Wenn ich aus einem Javascript eine Zahl in den Objektbau schreibe:
var zahl = 123.456; function TEST (){ createState("javascript.0.TESTOBJEKT.Zahl", /* Initial Value */ parseFloat(zahl), function () { console.log("Objekt erstellt"); }); }
Dann sieht es so aus:
{ "common": { "name": "javascript.0.TESTOBJEKT.Zahl", "role": "state", "type": "mixed", "custom": { "sql.0": { "enabled": true, "storageType": "Number", "counter": false, "aliasId": "TestZahl",
Im Falle Homematic IP steht dann in der SQL-Datenbank die Zahl, die ich auch im Objektbaum sehe.
Beim JavaScript steht "NULL" in dem Value.Was mache ich im JavaScript falsch, dass dazu führt, dass der Typ "mixed" ist, von dem State, anstelle von Nummer?
-
@sven-schumacher sagte in Zahl aus JS schafft es nicht in die MySQL-DB:
createState
Du musst bei einem
createState
ja auch noch angeben von welchen Typ der Datenpunkt sein soll, welcher Startwert, Einheit usw.var zahl = 123.456; function TEST (){ createState("javascript.0.TESTOBJEKT.Zahl", /* Initial Value */ parseFloat(zahl), {name: "Name oder weglassen", type: 'number', role: 'value'}, function () { console.log("Objekt erstellt"); }); }
könnte klappen (ungetestet).
Mit hat mal einer das hier zusammengestrickt um Datenpunkte anzulegen und danach auch sofort nutzen zu können:
async function CreateMyStatesAndStartup(){ try { DebugWarning("Startup: Erstelle ggf. Datenpunkte ..."); // POWER await createStateAsync(s_state_FullPath + ".POWER", false, { type: 'boolean', read: true, write: true, role: "switch", name: s_DeviceName + s_Suffix + '.POWER' }); // RSSI await createStateAsync(s_state_FullPath + ".RSII", 0, { type: 'number', read: true, write: false, name: 'WLAN Stärke in %' }); } catch(error) { DebugWarning(error); log(error); } }
Das nutze ich in dieser Art in meinen Skripten
-
@sven-schumacher sagte: aus einem Javascript eine Zahl in den Objektbau schreibe:
Mit createState(id, init, common, callback) schreibt nicht in Datenpunkte, sondern man erstellt sie. Beim Erstellen muss man auch common-Attribute übergeben, wie
createState("javascript.0.TESTOBJEKT.Zahl", zahl, {type: 'number', role: 'value', name: 'Testzahl', read: true, write: false}, function () { console.log("Objekt erstellt"); });
-
Also so?
// Prüfen, ob der Zustand bereits existiert existsState(id, (err, exists) => { if (!err && exists) { // Zustand existiert bereits, aktualisieren setState(id, value); } else { // Zustand existiert noch nicht, erstellen createState(id, value, true, {name: 'Value', type: 'number', read: true, write: false }); } }
Damit erhalte ich jetzt die richtigen Werte, aber dafür für jeden Schreibvorgang eine Warnung:
18:10:23.848 warn javascript.0 (957) at script.js.common.Messwerte:36:11 18:10:23.868 warn javascript.0 (957) at script.js.common.Messwerte:36:11 18:10:23.876 warn javascript.0 (957) at script.js.common.Messwerte:36:11 18:10:23.882 warn javascript.0 (957) at script.js.common.Messwerte:36:11 18:10:23.890 warn javascript.0 (957) at script.js.common.Messwerte:36:11 18:10:23.897 warn javascript.0 (957) at script.js.common.Messwerte:36:11
wobei bei mir Zeile 36 die Zeile ist mit "setState(id, value);"
-
@sven-schumacher sagte: Also so?
Das geht einfacher synchron (ohne Callback-Funktion):
if (existsState(id)) setState(id, value, true); else createState(id, value, {name: 'Value', type: 'number', role: 'value', read: true, write: false});
-
So habe ich das jetzt:
if (existsState(id)) { // Zustand existiert bereits, aktualisieren console.log("Exist:"+field); setState(id, value,true); } else { // Zustand existiert noch nicht, erstellen console.log("New:"+field); switch (field) { case "dateTime": createState(id, value, true, {name: 'timestamp', type: 'string', read: true, write: false }); break; case "lat": createState(id, value, true, {name: 'Latitude', type: 'string', read: true, write: false }); break; case "lon": createState(id, value, true, {name: 'Longitude', type: 'string', read: true, write: false }); break; case "systemOfUnits": createState(id, value, true, {name: 'systemofunits', type: 'string', read: true, write: false }); break; case "name": createState(id, value, true, {name: 'name', type: 'string', read: true, write: false }); break; case "source": createState(id, value, true, {name: 'source', type: 'string', read: true, write: false }); break; case "value": createState(id, value, true, {name: 'value', type: 'number', read: true, write: false }); break; default: createState(id, value, true, {name: 'misc', type: 'string', read: true, write: false }); break; } } Warnungen kommen mur noch, wenn der State schon existiert und es genau um LAT und LON geht. Diese sollen als STRING gespeichert werden ...
-
@sven-schumacher sagte: Diese sollen als STRING gespeichert werden ...
Enthalten sie auch einen String? Normalerweise sind das Zahlen.
-
@paul53 Es sind Zahlen, sollen aber als String gespeichert werden.
Beim ersten Anlegen ist alles fein. Nur wenn dann ab dem zweiten Schreiben statt createstate dann setstate zum Einsatz kommt, gibt es eine Warnung.
Die Zahl/String steht ja auch lesbar im Objektbaum.Abgesehen davon habe ich nach wie vor das Problem, dass einige Zahlen (type:number) beim Schreiben in MySQL mit der SQL-Protokollierung als Zahl in der Tabelle ts_number landen (fein!) und andere, die absolut genau die gleichen Attribute haben und ebenfalls Zahlen sind, werden in ts_string als String geschrieben.
Auch das händische "Speichern als: Zahl" in der SQL-Protokolierung ändert daran so einfach gar nichts.
Hier der Luftdruck, der aber als String in der DB landet:
{ "common": { "name": "value", "type": "number", "read": true, "write": false, "role": "state", "custom": { "sql.0": { "enabled": true, "storageType": "Number", "counter": false, "aliasId": "KMW_Luftdruck", "debounceTime": 1000, "blockTime": 1000, "changesOnly": false, "changesRelogInterval": 900, "changesMinDelta": 0, "ignoreBelowNumber": "", "disableSkippedValueLogging": false, "retention": 63072000, "customRetentionDuration": 365, "maxLength": 0, "enableDebugLogs": false, "debounce": 1000 } } }, "native": {}, "type": "state", "_id": "javascript.0.Kachelmann.Messwerte.data.pressureMsl.value", "acl": { "object": 1638, "state": 1638, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1684005933055 }
Und hier die Windgeschwindigkeit, die - so wie gewünscht - als Zahl in der DB landet:
{ "common": { "name": "value", "type": "number", "read": true, "write": false, "role": "state", "custom": { "sql.0": { "enabled": true, "storageType": "Number", "counter": false, "aliasId": "KMW_Windgeschwindigkeit", "debounceTime": 1000, "blockTime": 1000, "changesOnly": false, "changesRelogInterval": 900, "changesMinDelta": 0, "ignoreBelowNumber": "", "disableSkippedValueLogging": false, "retention": 63072000, "customRetentionDuration": 365, "maxLength": 0, "enableDebugLogs": false, "debounce": 1000 } } }, "native": {}, "type": "state", "_id": "javascript.0.Kachelmann.Messwerte.data.windSpeed.value", "acl": { "object": 1638, "state": 1638, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1684005987573 }
-
@sven-schumacher sagte: dann setstate zum Einsatz kommt, gibt es eine Warnung.
Die Warnung kommt, wenn man einen anderen Typ (Zahl) in einen Datenpunkt vom Typ "string" schreibt. Wenn man einen String im Datenpunkt haben will muss man vorher in einen String wandeln.
-
@paul53 Ja, das habe ich jetzt verstanden. Dabke schon einmal bis hierhin! Das Script ist jetzt fein!
Das war EINES der Probleme und damit jetzt auch gelöst. Ich bin von einer automatischen Typumwandlung ausgegangen. Aber das gibt es hier eben nicht.
Das ANDERE PROBLEM bleibt, dass bei mir richtig angelegte "number"-Werte im Objektbaum teilweise als STRING in der MySQL-DB landen. Hier wird gegen meinen Willen, aus einer gültigen "number" im Objektbaum ein String, ganz ohne Umwandlung. Das macht die Auswertung in Grafana dann natürlich schwierig.
3 von 7 Werten werden richtig als Zahl gespeichert.
4 von 7 Werten werden falsch in einen String umgewandelt.Das hat vermutlich nichts mehr mit Javascript zu tun, wie ich ursprünglich dachte.
Mein letzter Beitrag hier drüber zeigt zwei der States. Falls ich nichts übersehen habe, sind sie in den wichtigsten Punkten identische "number"-States.
In der SQL-Protokollierung werden beide identisch in die DB aufgenommen. Und doch ist dann einer ein String und einer eine Zahl.Wo kann ich suchen?
-
@sven-schumacher sagte: 4 von 7 Werten werden falsch in einen String umgewandelt.
Sicher, dass sie als Zahl vorliegen? Um das zu prüfen, gibt es
log('Typ von Luftdruck: ' + typeof getState('javascript.0.Kachelmann.Messwerte.data.pressureMsl.value').val);
-
@paul53 ich teste das später. Danke schon mal für den Tipp!
-
Hat noch der Punkt vor dem val gefehlt.
Habs für beide Beispiele ergänzt.log('Typ von Luftdruck: ' + typeof getState('javascript.0.Kachelmann.Messwerte.data.pressureMsl.value').val); log('Typ von Windgeschw: ' + typeof getState('javascript.0.Kachelmann.Messwerte.data.windSpeed.value').val);
Und es sind beides Objekte vom Typ "number".
Trotzdem landet eines der Objekte als STRING in der DB und das andere als NUMBER19:15:07.801 info javascript.0 (15700) Start javascript script.js.common.Skript_1 19:15:07.823 info javascript.0 (15700) script.js.common.Skript_1: Typ von Luftdruck: number 19:15:07.824 info javascript.0 (15700) script.js.common.Skript_1: Typ von Windgeschw: number 19:15:07.825 info javascript.0 (15700) script.js.common.Skript_1: registered 0 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions