NEWS
CMI UVR16X2
-
Hallo zusammen
Ich bin derzeit am ablösen meiner fhem Sache dran. Nun stehe ich aber mit meiner Heizungssteuerung von TA massiv auf dem Schlauch. Ich habe den Modbus-Adapter eingerichtet und auch die IP des CMI eingegeben, auch habe ich als TCP und Slave definiert aber der kann sich nicht verbinden. Adapter leibt gelb.
Ach so, ja die fhem Instanz habe ich natürlich gestoppt, resp. auf andere IP umgeleitet, als sollte die Schnittstelle frei sein.Aus den verschiedenen Einträge hier im Forim komme ich nicht schlau. Gibt es jemanden der einem Anfänger etwas helfen kann?
Viele Dank
Andi -
Hallo
also mein Fehler lag am Docker.. hatte dort vergessen den PORT 502 weiterzuleiten
-
@altas
Hallo, ich habe auch das Problem, wie war die Lösung genau ?Vielen Dank
-
Hallo Oliver, also bei mir läuft nun schon länger dieses Skript. Über die Modbus Schnittstelle habe ich es schlicht nicht hin gekriegt. Für den Modbus musst du sicher auch noch auf dem CMI ganz viel einrichten. Soweit ich mich erinnern mag, musst du alle Werte aus dem CAN importieren und dann auf dem Modbus-Out weiterleiten. Da ich aber keinen voll Zugriff auf die UVR hatte, habe ich das mit externer Hilfe dann mit diesem Skript hingekriegt.
Aber frage mich bitte nicht was das Skript genau alles macht. Ich kann nur sagen es läuft und schreibt jede Minute die Werte in die Datentabelle rein, daraus habe ich dann einen Alias gemacht.
Bei ersten Ausführen musste ich irgendwo noch das "false" auf "true" wechseln. (ich meinte dort bei den "Hilfsvariablen".
var request = require("request"); //username & password for CMI var username = "username"; var password = "Passwort"; var auth = "Basic " + new Buffer(username + ":" + password).toString("base64"); //URL to CMI Interface, only change IP var url1 = 'http://<IP_vom_CMI>/INCLUDE/api.cgi?jsonnode=2&jsonparam=I,O'; // JSON with Unit from CMI_JSON_API_V3 https://www.ta.co.at/downloads/datei/17511763-cmi-json-api/ var unitJson = { "0": "", "1": "°C", "2": "W/m²", "3": "l/h", "4": "Sek", "5": "Min", "6": "l/Imp", "7": "K", "8": "%", "10": "kW", "11": "kWh", "12": "MWh", "13": "V", "14": "mA", "15": "Std", "16": "Tage", "17": "Imp", "18": "KΩ", "19": "l", "20": "km/h", "21": "Hz", "22": "l/min", "23": "bar", "24": "", "25": "km", "26": "m", "27": "mm", "28": "m³", "35": "l/d", "36": "m/s", "37": "m³/min", "38": "m³/h", "39": "m³/d", "40": "mm/min", "41": "mm/h", "42": "mm/d", "43": "Aus/Ein", "44": "Nein/Ja", "46": "°C", "50": "€", "51": "$", "53": "", "54": "°", "56": "°", "57": "Sek", "58": "", "59": "%", "60": "Uhr", "63": "A", "65": "mbar", "66": "Pa", "67": "ppm" }; // Hilfsvariablen var stateanlegen = false; var state1anlegen = false; var llog = true; // loging ein/aus (true/false) // zeitlich die Abfrage wiederhohlen //jede x minute schedule ("*/1 * * * *", function () { readurl1(); }); function readurl1() { readJson(url1, function (err, json) { if (!err) { if (json['Statuscode'] === 0) { // console.log('ReadStatus_Knoten 1 '+json['Status']); setDataObjectsKnoten1(json); } } else { log("Fehler beim Auslesen des Knoten 1 JSON. Keine Daten erhalten.", "warn"); log("Errorcode " + json['Statuscode'], "warn"); } }); } function readJson(url, callback) { request({ url: url, headers: { "Authorization": auth } }, function (error, response, body) { if (body) { var result = body.replace(/ /g, ''); //alle Leerzeichen durch Unterstrich ersetzten var jdata = JSON.parse(result); //Json Array erzeugen callback(null, jdata); } else { log(error, "warn"); callback(error, null); } }); } function setDataObjectsKnoten1(jsondata) { // console.log(jsondata['Data']['Inputs']['0']['Value']['Value']); // console.log(jsondata['Data']['Inputs']['0']['Value']['Unit']); if (stateanlegen === true) { // User Variablen anlegen Achtung keine Punkte im Namen verwenden. createState('0_userdata.0.UVR16x2.Header.Version', { name: 'Version', type: 'number', unit: '', write: true, read: true }); createState('0_userdata.0.UVR16x2.Header.Device', { name: 'Device', type: 'string', unit: '', write: true, read: true }); createState('0_userdata.0.UVR16x2.Header.Timestamp', { name: 'Timestamp', type: 'number', unit: '', write: true, read: true }); var i = 0; for (i = 0; i <= 15; i++) { if(Object.keys(jsondata['Data']['Inputs']).includes(i.toString())) { var inputsUnit = unitJson[jsondata['Data']['Inputs'][i]['Value']['Unit']]; if (i < 9) { createState('0_userdata.0.UVR16x2.Input_Number0' + jsondata['Data']['Inputs'][i]['Number'], '', { name: 'Input_Number0' + jsondata['Data']['Inputs'][i]['Number'] + '_' + jsondata['Data']['Inputs'][i]['AD'], type: 'number', unit: '' + inputsUnit, write: true, read: true }); } else { createState('0_userdata.0.UVR16x2.Input_Number' + jsondata['Data']['Inputs'][i]['Number'], '', { name: 'Input_Number' + jsondata['Data']['Inputs'][i]['Number'] + '_' + jsondata['Data']['Inputs'][i]['AD'], type: 'number', unit: '' + inputsUnit, write: true, read: true }); } } } i = 0; for (i = 0; i <= 15; i++) { if(Object.keys(jsondata['Data']['Outputs']).includes(i.toString())) { var outputsUnit = unitJson[jsondata['Data']['Outputs'][i]['Value']['Unit']]; if (i < 9) { createState('0_userdata.0.UVR16x2.Output_Number0' + jsondata['Data']['Outputs'][i]['Number'], '', { name: 'Output_Number' + jsondata['Data']['Outputs'][i]['Number'] + '_' + jsondata['Data']['Outputs'][i]['AD'], type: 'number', unit: '' + outputsUnit, write: true, read: true }); if (jsondata['Data']['Outputs'][i]['AD'] === 'A') { createState('0_userdata.0.UVR16x2.Output_Number_State0' + jsondata['Data']['Outputs'][i]['Number'], '', { name: 'Output_Number_State' + jsondata['Data']['Outputs'][i]['Number'] + '_' + jsondata['Data']['Outputs'][i]['AD'], type: 'number', unit: '' + outputsUnit, write: true, read: true }); } } else { // set +jsondata['Data']['Outputs'][i]['Value']['Value'], createState('0_userdata.0.UVR16x2.Output_Number' + jsondata['Data']['Outputs'][i]['Number'], '', { name: 'Output_Number' + jsondata['Data']['Outputs'][i]['Number'] + '_' + jsondata['Data']['Outputs'][i]['AD'], type: 'number', unit: '' + outputsUnit, write: true, read: true }); if (jsondata['Data']['Outputs'][i]['AD'] === 'A') { // set +jsondata['Data']['Outputs'][i]['Value']['Value'], createState('0_userdata.0.UVR16x2.Output_Number_State' + jsondata['Data']['Outputs'][i]['Number'], '', { name: 'Output_Number_State' + jsondata['Data']['Outputs'][i]['Number'] + '_' + jsondata['Data']['Outputs'][i]['AD'], type: 'number', unit: '' + outputsUnit, write: true, read: true }); } } } } console.log("Variablen Knoten 1 angelegt"); state1anlegen = true; } else { //Variablen setstate setState('0_userdata.0.UVR16x2.Header.Version', jsondata['Header']['Version']); setState('0_userdata.0.UVR16x2.Header.Device', jsondata['Header']['Device']); setState('0_userdata.0.UVR16x2.Header.Timestamp', jsondata['Header']['Timestamp']); i = 0; for (i = 0; i <= 15; i++) { if(Object.keys(jsondata['Data']['Inputs']).includes(i.toString())) { if (i < 9) { //set jsondata['Data']['Inputs'][i]['Value'],['Value'] setState('0_userdata.0.UVR16x2.Input_Number0' + jsondata['Data']['Inputs'][i]['Number'], jsondata['Data']['Inputs'][i]['Value']['Value']); } else { setState('0_userdata.0.UVR16x2.Input_Number' + jsondata['Data']['Inputs'][i]['Number'], jsondata['Data']['Inputs'][i]['Value']['Value']); } } } i = 0; for (i = 0; i <= 15; i++) { if(Object.keys(jsondata['Data']['Outputs']).includes(i.toString())) { if (i < 9) { setState('0_userdata.0.UVR16x2.Output_Number0' + jsondata['Data']['Outputs'][i]['Number'], jsondata['Data']['Outputs'][i]['Value']['Value']); if (jsondata['Data']['Outputs'][i]['AD'] === 'A') { setState('0_userdata.0.UVR16x2.Output_Number_State0' + jsondata['Data']['Outputs'][i]['Number'], jsondata['Data']['Outputs'][i]['Value']['State']); } } else { setState('0_userdata.0.UVR16x2.Output_Number' + jsondata['Data']['Outputs'][i]['Number'], jsondata['Data']['Outputs'][i]['Value']['Value']); if (jsondata['Data']['Outputs'][i]['AD'] === 'A') { setState('0_userdata.0.UVR16x2.Output_Number_State' + jsondata['Data']['Outputs'][i]['Number'], jsondata['Data']['Outputs'][i]['Value']['State']); } //setState('javascript.0.PoolController.ADC'+[i-1], parseFloat(Number(wert).toFixed(2))); } } } } }
Irgendwo habe ich gelesen das man anscheinend auch von TA die CAN-Bus Daten bekommen würde. Heute würde ich es vermutlich so machen und von TA den "CAN-Bus Abzweig" einbauen und schauen das ich mittels Iobroker-Multihost einen kleinen RaspberryPi mit CAN Schnittstelle das ganze übernehmen würde. Aus meiner Sicht hat das den grossen Vorteil das der Master sich nicht mit solchen Dingen beschäftigen muss und der Slave kann solange arbeiten wie er will, dafür wären die Daten via CAN dann sicher auch ganz aktuell. Braucht aber dann natürlich auch einen Softwareentwickler Zugriff auf das ganze TA System weil auch damit müsste man dann die Daten an den zusätzlichen CAN-Device senden.
-
@andibr Hallo,
das mit dem Json von Dir ist mega interessant - wo hast du das im IO eingebaut ?
Ich habe heute endlich das MODBus zum laufen bekommen - aber Json ist interessant!
Viele Grüsse Oli
-
@oliver-panarotto said in CMI UVR16X2:
das mit dem Json von Dir ist mega interessant - wo hast du das im IO eingebaut ?
Ich verstehe im Moment nicht genau was du mit "IO" meinst?
Ich habe das einfach als Skript eingefügt und dann hat es mir die Datenpunkte erstellt
Daraus habe ich dann mit dem Alias brauchbare Datenpunkte gebastelt.
-
@andibr hallo ich meine wo im IO_Broker ? hast du das eingefügt und wie macht man Alias punkte ?
-
@oliver-panarotto said in CMI UVR16X2:
@andibr hallo ich meine wo im IO_Broker ? hast du das eingefügt und wie macht man Alias punkte ?
Ich habe mir bei den Skripten einen neuen Ordner erstellt und dort ein neues Skript mit Javascript. Dort rein habe ich dann dieses Skript kopiert und die Zugansdaten zu meinem CMI angepasst. Danach musste ich noch im Skript aus dem "false" ein "true" machen:
// Hilfsvariablen var stateanlegen = false; // beim 1.Mal auf true stellen var state1anlegen = false; // beim 1.Mal auf true stellen
So hat er mir dann die Datenpunkte angelegt. Danach zurückstellen und ab jetzt sollte er jede Minute die Daten abholen und reinschreiben, Schneller als jede Minute (60s) lässt das CMI nicht zu und blockt das einfach ohne Meldung einfach ab oder gibt keine Antwort.
Danach kann man mit dem Adpater "Alias-Manager" sich die Datenpunkte "zurechtbiegen" und weiter verwenden.
Seither läuft es beim mir und ich habe mir auch eine eigene Betriebstundenzählung gemacht, weil mein Heizungsinstallateur behauptet hat, er können mir diese Zahlen nicht exportieren. Vieleicht kann man die via ModBus oder CAN exportieren?
-
@andibr sagte in CMI UVR16X2:
Vieleicht kann man die via ModBus oder CAN exportieren?
Hast du das hier gesehen: https://forum.iobroker.net/topic/26032/gelöst-modbus-adapter-uvr-16x2-cmi
-
@andibr Hallo,
vielen Dank für die Ausführungen.
Ich habe es auch mit MODBUS geschaft, das läuft nun bei mir sehr gut .... Export und Import. -
@jey-cee said in CMI UVR16X2:
@andibr sagte in CMI UVR16X2:
Vieleicht kann man die via ModBus oder CAN exportieren?
Hast du das hier gesehen: https://forum.iobroker.net/topic/26032/gelöst-modbus-adapter-uvr-16x2-cmi
Das bedingt aber das man vollen Zugriff auf die Steuerung (resp. das Interface CMI) hat. Mein Heizungsmonteur will mir eben genau das nicht geben. Ich frage mich jetzt mal nicht wieso, denn diese Antwort kenne ich selber schon: "dann machst du wieder was".
Ich habe es mit den paar wenigen Datenpunkten die ich zur Verfügung hatte, eben nicht geschaft.
Bekommt ihr über die Modbus-Schnittstelle auch die Betriebszeiten geliefert? Weil mein Iobroker intern gebastelte Zähler ist etwas ungenau. Mein Heizunginstallateur behauptet eben die Betriebszähler könne er nicht auf das CMI rausschreiben.