Closed HMelzer closed 2 years ago
Im Prinzip ja. Leider habe ich keine Gateways im Einsatz, deshalb kann ich das nicht nachstellen, bzw. anpassen. Wie sieht denn die Debugausgabe der rssiInfo
Abfrage mit Gateway aus?
Anbei habe ich mal eine auf das Wesentliche gekürzte Datei mit der Debugausgabe des rssiInfo
Knotens angehängt.
Zur Information: OEQ0606784 ist die CCU, in diesem Falle die RaspberryMatic, REQ1359302 ist das Gateway.
QEQ0714358, QEQ0714741 und QEQ1054845 hängen direkt an der CCU, NEQ0968020, HM-TPH0001, HM-TPH0002, HM-TPH0003 hängen am Gateway. Die Sensoren, die mit HM-beginnen sind Eigenbaukomponenten, die immer schon nur einen RSSI-Wert zurückgegeben haben. Relevant wäre hier eher der Sensor NEQ0968020, der ja beide Werte zurückgibt.
Hatte es versehentlich geschlossen.
Puh, da bricht irgendwie die gesamte bisherige Logik zusammen. Bitte mal das komplette Objekt und wenn möglich einen passenden RSSI Screenshot aus der "DevConfig" Seite der CCU anhängen.
Wie soll ich das gesamte Objekt der Debug-Ausgabe speichern? Siehst du da die Möglichkeit, die ich derzeit nicht sehe. Auch der RSSI-Screenshot wird mindestens in drei Objekten zu speichern sein.
Wäre das so recht? rssiInfoObjekt.txt
Hier noch die Screenshots aus dem "DevConfig":
Wäre das so recht?
Danke. Ist das der Output, der bei Dir im Node-Red Debug Fenster erscheint, beispielsweise bei sowas:
[{"id":"2897afe7.2e3048","type":"ccu-rpc","z":"721e71e2.b201b8","name":"","ccuConfig":"38263145.35ea0e","iface":"BidCos-RF","method":"rssiInfo","params":"[]","topic":"${CCU}/${Interface}/${Method}","x":300,"y":1080,"wires":[["52a73334.5b7dc4"]]},{"id":"52a73334.5b7dc4","type":"debug","z":"721e71e2.b201b8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":450,"y":1080,"wires":[]},{"id":"1ea13736.5ba511","type":"inject","z":"721e71e2.b201b8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":1080,"wires":[["2897afe7.2e3048"]]},{"id":"38263145.35ea0e","type":"ccu-connection","name":"localhost","host":"localhost","regaEnabled":true,"bcrfEnabled":true,"iprfEnabled":true,"virtEnabled":true,"bcwiEnabled":false,"cuxdEnabled":false,"regaPoll":true,"regaInterval":"30","rpcPingTimeout":"60","rpcInitAddress":"192.168.178.18","rpcServerHost":"192.168.178.18","rpcBinPort":"2047","rpcXmlPort":"2048","tls":false,"inSecure":false,"authentication":false,"username":"","password":"","queueTimeout":"5000","queuePause":"250","contextStore":"default"}]
--> Code kopieren und in Node-Red importieren
Debug Output sollte dann etwa so aussehen:
Wenn das so genügt:
Bitte einmal testen:
[{"id":"43c7216a.58de68","type":"function","z":"721e71e2.b201b8","name":"Extract RSSI values","func":"const rssi = msg.payload,\n DBValues = [];\n\nlet msg2 = {},\n centrals = [];\n\n// Identify available centrals: CCU, Gatesways, etc\n// If multiple centrals exist then the \"BidCoS-RF\" object exists\nif (rssi['BidCoS-RF']) {\n centrals = Object.keys(rssi['BidCoS-RF']);\n} else {\n // Object is unordered: Make sure we do not catch the CCU\n const temp0 = Object.keys(rssi)[0];\n const temp1 = Object.keys(rssi)[1];\n if (Object.keys(rssi[temp0]).length === 1) {\n centrals = (Object.keys(rssi[temp0]));\n } else if (Object.keys(rssi[temp1]).length === 1) {\n centrals = (Object.keys(rssi[temp1]));\n } else {\n node.error('No central identified');\n }\n}\n\nfor (const central of centrals) {\n for (const MyDevice of Object.keys((rssi)[central])) {\n if (MyDevice !== 'BidCoS-RF') {\n const device = {\n central: central,\n device: MyDevice,\n down: (rssi[central][MyDevice][1] === 65536)? 'N/A':rssi[central][MyDevice][1],\n up: (rssi[central][MyDevice][0] === 65536)? 'N/A':rssi[central][MyDevice][0]\n };\n DBValues.push(device);\n }\n }\n}\n\nmsg2 = {\n payload: DBValues,\n topic: msg.topic\n};\n\nreturn msg2;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":420,"y":640,"wires":[["6982e9d1.146ed"]]},{"id":"6982e9d1.146ed","type":"change","z":"721e71e2.b201b8","name":"ui_control","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnResized\":\"function(column){var newColumn = {field: column._column.field, visible: column._column.visible, width: column._column.width, widthFixed: column._column.widthFixed, widthStyled: column._column.widthStyled};this.send({topic:this.config.topic,ui_control:{callback:'columnResized',columnWidths:newColumn}});}\",\"columnMoved\":\"function(column, columns){var newColumns=[];columns.forEach(function (column) {newColumns.push({'field': column._column.field});});this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}});}\",\"layout\":\"fitColumns\",\"columns\":[{\"title\":\"Gerät\",\"field\":\"device\",\"formatter\":\"function(cell, formatterParams, onRendered){return cell.getValue();}\"},{\"title\":\"<div style='text-align:center'><i class='fa fa-arrow-circle-up' aria-hidden='true'></i></div>\",\"align\":\"center\",\"field\":\"up\",\"formatter\":\"function(cell, formatterParams){ var value = cell.getValue(); if (value >= -50) { cell.getElement().style.backgroundColor='#00cc44'; } else if (value <= -51 && value >= -100) { cell.getElement().style.backgroundColor='#66ff66'; } else if (value <= -101 && value >= -120) { cell.getElement().style.backgroundColor='#ff8c66'; } else if (value <= -120) { cell.getElement().style.backgroundColor='#ff6666'} return value;}\"},{\"title\":\"<div style='text-align:center'><i class='fa fa-arrow-circle-down' aria-hidden='true'></i></div>\",\"field\":\"down\",\"align\":\"center\",\"formatter\":\"function(cell, formatterParams){ var value = cell.getValue(); if (value >= -50) { cell.getElement().style.backgroundColor='#00cc44'; } else if (value <= -51 && value >= -100) { cell.getElement().style.backgroundColor='#66ff66'; } else if (value <= -101 && value >= -120) { cell.getElement().style.backgroundColor='#ff8c66'; } else if (value <= -120) { cell.getElement().style.backgroundColor='#ff6666'} return value;}\"}],\"movableColumns\":true,\"groupBy\":\"central\"},\"customHeight\":55}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":640,"wires":[["b30e50c8.b1e23"]]},{"id":"b30e50c8.b1e23","type":"ui_table","z":"721e71e2.b201b8","group":"4bbfb1c3.d86a","name":"RSSI Table","order":2,"width":"6","height":"12","columns":[],"outputs":1,"cts":true,"x":750,"y":640,"wires":[[]]},{"id":"4bbfb1c3.d86a","type":"ui_group","name":"CCU","tab":"189e0ea3.dd5dd1","order":2,"disp":true,"width":"6","collapse":false},{"id":"189e0ea3.dd5dd1","type":"ui_tab","name":"System","icon":"computer","order":7}]
Bevor ich es vergesse:
Bitte hier auch noch den kompletten Debug Output als Text rein kopieren / anhängen.
Sieht erst einmal soweit gut aus, obwohl ja alle BidCos-RF-Geräte nun doppelt aufgeführt werden, einmal für die CCU, einmal für das Gateway, Tatsächlich kommunizieren diese aber ja nur mit jeweils einem Partner. Das da auch Werte zum/für den anderen Partner generiert werden, die sich so auch unterscheiden ist sicher richtig, aber im vorliegenden Fall wohl uninteressant. Wie schon am 25.02. erwähnt hier noch mal beispielhaft folgende Information.
Zur Information: OEQ0606784 ist die CCU, in diesem Falle die RaspberryMatic, REQ1359302 ist das Gateway.
QEQ0714358, QEQ0714741 und QEQ1054845 hängen direkt an der CCU, NEQ0968020, HM-TPH0001, HM-TPH0002, HM-TPH0003 hängen am Gateway.
Das gewünschte Debug-Output folg hier: Wenn gewünscht, kann ich natürlich eine vollständige Liste der einzelnen Zuordnungen liefern.
Ich habe mir gerade noch einmal die Debug-Ausgabe des rssiInfo-Knotens angesehen. Da ist mit tatsächlich nicht aufgefallen, wonach man unterscheiden kann, woran ein Gerät hängt.
Sieht erst einmal soweit gut aus, obwohl ja alle BidCos-RF-Geräte nun doppelt aufgeführt werden, einmal für die CCU, einmal für das Gateway, Tatsächlich kommunizieren diese aber ja nur mit jeweils einem Partner.
Ja, leider geht diese Information aus der RSSI Abfrage nicht hervor. Siehe auch den Screenshot aus "DevConfig". Was die Methode in der Redmatic macht ist nichts anderes.
Bezüglich der Duty Cycle Thematik:
Wie würdest du es dir vorstellen? Das Zeigerinstrument macht bei zwei oder mehr Duty Cycle Werten nur noch eingeschränkt Sinn:
Tut mir leid, dass ich erst so spät antworte, aber ich quäle mich gerade mit einem PID-Regler herum und, es gib da auch eben noch Anderes. Das Zeigerinstrument ist ja nun mal wenig geignet mehr als eine Ausgabe zu machen. Aus meiner Sicht reicht es doch vollkommen die Werte als Balkendiagram in einer Chart-Node darzustellen. Vorteilhaft wäre wohl aber auch, das nicht in einer Node zu machen, sondern eben in mehreren (ähnlich, wie es ja auch auf der Startseite der CCU ist). Die Chart-Node Duty Cycle (1 hour) kann ja so bleiben und mit den Werten der CCU und des/der Gateways gefüllt werden.
So hab ich es jetzt mal gelöst. An einer Visualisierung kann und darf ja jeder basteln wie er möchte
Anbei mal die letzten Stände:
RSSI:
[{"id":"43c7216a.58de68","type":"function","z":"721e71e2.b201b8","name":"Extract RSSI values","func":"const rssi = msg.payload,\n DBValues = [];\n\nlet msg2 = {},\n centrals = [];\n\n// Identify available centrals: CCU, Gatesways, etc\n// If multiple centrals exist then the \"BidCoS-RF\" object exists\nif (rssi['BidCoS-RF']) {\n centrals = Object.keys(rssi['BidCoS-RF']);\n} else {\n // Object is unordered: Make sure we do not catch the CCU\n const temp0 = Object.keys(rssi)[0];\n const temp1 = Object.keys(rssi)[1];\n if (Object.keys(rssi[temp0]).length === 1) {\n centrals = (Object.keys(rssi[temp0]));\n } else if (Object.keys(rssi[temp1]).length === 1) {\n centrals = (Object.keys(rssi[temp1]));\n } else {\n node.error('No central identified');\n }\n}\n\nfor (const central of centrals) {\n for (const MyDevice of Object.keys((rssi)[central])) {\n if (MyDevice !== 'BidCoS-RF') {\n const device = {\n central: central,\n device: MyDevice,\n down: (rssi[central][MyDevice][1] === 65536)? 'N/A':rssi[central][MyDevice][1],\n up: (rssi[central][MyDevice][0] === 65536)? 'N/A':rssi[central][MyDevice][0]\n };\n DBValues.push(device);\n }\n }\n}\n\nmsg2 = {\n payload: DBValues,\n topic: msg.topic\n};\n\nreturn msg2;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":420,"y":640,"wires":[["6982e9d1.146ed"]]},{"id":"6982e9d1.146ed","type":"change","z":"721e71e2.b201b8","name":"ui_control","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnResized\":\"function(column){var newColumn = {field: column._column.field, visible: column._column.visible, width: column._column.width, widthFixed: column._column.widthFixed, widthStyled: column._column.widthStyled};this.send({topic:this.config.topic,ui_control:{callback:'columnResized',columnWidths:newColumn}});}\",\"columnMoved\":\"function(column, columns){var newColumns=[];columns.forEach(function (column) {newColumns.push({'field': column._column.field});});this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}});}\",\"layout\":\"fitColumns\",\"columns\":[{\"title\":\"Device\",\"field\":\"device\",\"formatter\":\"function(cell, formatterParams, onRendered){return cell.getValue();}\"},{\"title\":\"<div style='text-align:center'><i class='fa fa-arrow-circle-up' aria-hidden='true'></i></div>\",\"align\":\"center\",\"field\":\"up\",\"formatter\":\"function(cell, formatterParams){ var html_excel = 'style=\\\"color:#00cc44\\\"></i>'; var html_good = 'style=\\\"color:#66ff66\\\"></i>'; var html_aver = 'style=\\\"color:#ff8c66\\\"></i>'; var html_bad = 'style=\\\"color:#ff6666\\\"></i>'; var html='<i class=\\\"fa fa-circle fa-fw\\\" '; var value = cell.getValue(); if (value >= -50) { value = value + html + html_excel} else if (value <= -51 && value >= -100) { value = value + html + html_good; } else if (value <= -101 && value >= -120) { value = value + html + html_aver; } else if (value <= -120) { value = value + html + html_bad}; return value;}\"},{\"title\":\"<div style='text-align:center'><i class='fa fa-arrow-circle-down' aria-hidden='true'></i></div>\",\"field\":\"down\",\"align\":\"center\",\"formatter\":\"function(cell, formatterParams){ var html_excel = 'style=\\\"color:#00cc44\\\"></i>'; var html_good = 'style=\\\"color:#66ff66\\\"></i>'; var html_aver = 'style=\\\"color:#ff8c66\\\"></i>'; var html_bad = 'style=\\\"color:#ff6666\\\"></i>'; var html='<i class=\\\"fa fa-circle fa-fw\\\" '; var value = cell.getValue(); if (value >= -50) { value = value + html + html_excel} else if (value <= -51 && value >= -100) { value = value + html + html_good; } else if (value <= -101 && value >= -120) { value = value + html + html_aver; } else if (value <= -120) { value = value + html + html_bad}; return value;}\"}],\"movableColumns\":true,\"groupBy\":\"central\"},\"customHeight\":55}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":640,"wires":[["b30e50c8.b1e23"]]},{"id":"b30e50c8.b1e23","type":"ui_table","z":"721e71e2.b201b8","group":"b533a88a.2e9378","name":"RSSI Table","order":2,"width":"6","height":"11","columns":[],"outputs":1,"cts":true,"x":750,"y":640,"wires":[[]]},{"id":"b533a88a.2e9378","type":"ui_group","name":"CCU RSSI","tab":"189e0ea3.dd5dd1","order":7,"disp":true,"width":"6","collapse":false,"className":""},{"id":"189e0ea3.dd5dd1","type":"ui_tab","name":"System","icon":"computer","order":7}]
Duty Cycle:
[{"id":"15e18e55.7728e2","type":"function","z":"721e71e2.b201b8","name":"Extract DC values","func":"const DutyCycle = msg.payload,\n OutMsgs = [];\n\nfor (const element of DutyCycle) {\n const result = {\n topic: element['ADDRESS'],\n payload: element['DUTY_CYCLE']\n };\n OutMsgs.push(result);\n}\n\n\nreturn [OutMsgs];\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1330,"y":640,"wires":[["934645d.5a566b8","933be049.370c28"]]},{"id":"934645d.5a566b8","type":"ui_chart","z":"721e71e2.b201b8","name":"Duty Cycle (1 hour)","group":"4bbfb1c3.d86a","order":2,"width":0,"height":0,"label":"Duty Cycle (1 hour)","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1570,"y":620,"wires":[[]]},{"id":"933be049.370c28","type":"ui_chart","z":"721e71e2.b201b8","name":"Duty Cycle (Current)","group":"4bbfb1c3.d86a","order":1,"width":0,"height":0,"label":"Duty Cycle (Current)","chartType":"bar","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1580,"y":660,"wires":[[]]},{"id":"4bbfb1c3.d86a","type":"ui_group","name":"CCU Duty Cycle","tab":"189e0ea3.dd5dd1","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"189e0ea3.dd5dd1","type":"ui_tab","name":"System","icon":"computer","order":7}]
Duty Cycle muss dann so aussehen:
Es gefällt mir jetzt gut! Bei kleinen Duty Cycle-Werten ist ja kaum etwas zu sehen, da ist es aber auch nicht so wichtig. Wenn die Werte dann größer werden kann man das schon gut sehen. Eine kleine Anmerkung hätte ich noch: Gehen wir mal davon aus, dass es Anwender gibt, die mehr als ein Gateway haben, dann teilt ja die Chart-Node die vorhandene Breite unter der CCU und allen Gateways auf. Da könnte es unter Umständen knapp werden mit dem Platz für die Geräte-ID. Wäre es da nicht günstiger, die Balken waagerecht auszurichten?
Hier als Beispiel:
Da könnte es unter Umständen knapp werden mit dem Platz für die Geräte-ID. Wäre es da nicht günstiger, die Balken waagerecht auszurichten?
Die Idee ist gut und ich werde es so als Update für den Flow einchecken.
Nur als Randbemerkung: Die Flows, die ich geteilt habe, sollten ja kein fertiges Produkt sein, sondern nur ein bisschen zeigen, was mit Node Red im Allgemeinen und speziell im Zusammenhang mit der CCU möglich ist. Dadurch, dass alles offengelegt und durch Node Red auch die Einstiegshürde m.E. recht gering ist, kann jeder daran basteln wie er möchte (ich bin selber ein grauenvoller N00b-Coder). Bei mir verwaltet die CCU nur noch die Hardware und die gesamte Logik habe ich in NR ausgelagert (zumal ich die Logik und das Scripting in der CCU absolut gruselig finde)
Ich werde für meinen Flow sicher das Zeigerinstrument beibehalten, da ich keine Gateways habe und es deswegen schicker finde.
Ja, natürlich kann jeder in den Flows Anpasssungen nach seiner Fassong vornehmen. Aber es ist manchmal schon nicht schlecht, wenn man, insbesondere dann, wenn die Flows so umfangreich sind, eine geschlossene Lösung nutzen kann. ging mir jedenfalls so. Und ehrlicherweise tue ich mich schon auch schwer bei gewissen Anpassungen hinsichtlich Funktions-Nodes und auch Tabellen und Templates.
Ansonsten ist es auch bei mir so, dass die CCU eigentlich nur noch die Geräte verwaltet und die Funktionalität in Node-Red ausgelagert ist.
Wird in in der RaspberryMatic-Umgebung ein oder mehrerer Gateways verwendet, gibt es dafür, aber auch für die Zentrale keine Angaben zum Duty Cycle mehr. Auch die RSSI-Werte werden nicht mehr ausgegeben. Lässt sich hier eine Ergänzung implementieren?