LaMetric Anzeige mit HomeAssistant

Die LaMetric Anzeige eignet sich hervorragend, um weitere Informationen zum Stromverbrauch und Batterieladestand von HomeAssistant anzeigen zu lassen. Auch in diesem Fall unterstützt mich die NodeRed Integration hier.

In HomeAssistant gibt es auch eine direkte Intgeration (LaMetric – Home Assistant (home-assistant.io)). Diese kann aber nur Notfications anzeigen. Und das war mir ein bisschen zu wenig.

Als Vorbereitung habe ich folgende Grundlagen sichergestellt:

Dann habe ich den folgenden Flow erstellt:

Dieser Flow gibt beim Aufruf des definierten Endpoints die korrekte JSON Antwort zurück. Er ist dynamisch und ergänzt mir je nach Verbraucher die entsprechenden „Frames“. Wie so eine JSON Antwort aussehen kann, ist übrigens hier ausgezeichnet beschrieben. Die Icons findet ihr am Besten jeweils hier.

Hier das komplette Beispiel:

[{"id":"7b9046f8e332ea49","type":"tab","label":"LaMetric","disabled":false,"info":"","env":[]},{"id":"2b0554fccc7c10b9","type":"function","z":"7b9046f8e332ea49","name":"Tesla","func":"let obj = \n{\n    \"text\": msg.data + \"W\", \n    \"icon\": 7421,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1030,"y":320,"wires":[["4f7f181fb616955b"]]},{"id":"1f9cfe2d528de7da","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.easee_consumption_w","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":530,"y":340,"wires":[["2b0554fccc7c10b9"],["4f7f181fb616955b"]]},{"id":"4f7f181fb616955b","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":2,"halt_if":"090","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.heatpump_consumption_w","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":540,"y":420,"wires":[["938991cf2cacc5e4"],["2b4c726e81ee01eb"]]},{"id":"2b4c726e81ee01eb","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.whirlpool_heater_power","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":530,"y":500,"wires":[["2af5fabed15389e9"],["945e48d42d335a9a"]]},{"id":"938991cf2cacc5e4","type":"function","z":"7b9046f8e332ea49","name":"Wärmepumpe","func":"let obj = \n{\n    \"text\": msg.data + \"W\", \n    \"icon\": 24564,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":400,"wires":[["2b4c726e81ee01eb"]]},{"id":"2af5fabed15389e9","type":"function","z":"7b9046f8e332ea49","name":"Whirlpool","func":"let obj = \n{\n    \"text\": msg.data + \"W\", \n    \"icon\": 9196,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1040,"y":480,"wires":[["945e48d42d335a9a"]]},{"id":"64593cef4cb3d57c","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"gt","entity_id":"sensor.solar_power_w","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":510,"y":260,"wires":[["ebed37c27d4822ec"],["1f9cfe2d528de7da"]]},{"id":"ebed37c27d4822ec","type":"function","z":"7b9046f8e332ea49","name":"Solarstrom","func":"let obj = \n{\n    \"text\": msg.data + \"W\", \n    \"icon\": 34921,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1050,"y":240,"wires":[["1f9cfe2d528de7da"]]},{"id":"78ec095a22620f33","type":"http in","z":"7b9046f8e332ea49","name":"","url":"/meinlametric","method":"get","upload":false,"swaggerDoc":"","x":100,"y":60,"wires":[["2662394f2ee325a9"]]},{"id":"4d833c547c3a9433","type":"http response","z":"7b9046f8e332ea49","name":"","statusCode":"200","headers":{},"x":1220,"y":760,"wires":[]},{"id":"2662394f2ee325a9","type":"change","z":"7b9046f8e332ea49","name":"","rules":[{"t":"set","p":"counter","pt":"msg","to":"0","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"{\"frames\":[]}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":60,"wires":[["b6d84d81997e56e6"]]},{"id":"f04cc3ddeb847126","type":"function","z":"7b9046f8e332ea49","name":"Battery SOC Anzeige","func":"let icon = 2741;\nif (msg.data2>10) \n{\n    icon = 10892;\n} else if (msg.data2<-10) {\n    icon = 45705;\n} else if (msg.data>95) \n{\n    icon = 2741;\n} else if (msg.data>75) \n{\n    icon = 2740;\n} else if (msg.data>50) \n{\n    icon = 2739;\n} else if (msg.data>25) \n{\n    icon = 2738;\n} else {\n    icon = 2737;\n}\nlet obj = \n{\n    \"goalData\": \n    {\n        \"start\": 0,\n        \"end\": 100,\n        \"current\": msg.data,\n        \"unit\": \"%\"\n    },\n    \"icon\": icon\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1080,"y":120,"wires":[["f83ec808ed1613d0"]]},{"id":"8c713f3eade9052d","type":"function","z":"7b9046f8e332ea49","name":"Hausverbrauch","func":"let obj = \n{\n    \"text\": msg.data + \"W\", \n    \"icon\": 8441,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":180,"wires":[["64593cef4cb3d57c"]]},{"id":"945e48d42d335a9a","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.rocket_launch_1","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":510,"y":580,"wires":[["e2981eb637336a2e"]]},{"id":"e2981eb637336a2e","type":"switch","z":"7b9046f8e332ea49","name":"","property":"data.attributes.launch_24h_warning","propertyType":"msg","rules":[{"t":"eq","v":"true","vt":"str"},{"t":"neq","v":"true","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":730,"y":580,"wires":[["94d51672bb225a17"],["4d833c547c3a9433"]]},{"id":"94d51672bb225a17","type":"function","z":"7b9046f8e332ea49","name":"Rocket Launch - Vehicle","func":"let obj = \n{\n    \"text\": msg.data.attributes.vehicle, \n    \"icon\": 35531,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1090,"y":560,"wires":[["1f83d96b5aa5a8c1"]]},{"id":"f83ec808ed1613d0","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.house_consumption","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":520,"y":180,"wires":[["8c713f3eade9052d"]]},{"id":"b6d84d81997e56e6","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.battery_soc","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":600,"y":60,"wires":[["b4191f61db6d8824"]]},{"id":"b4191f61db6d8824","type":"api-current-state","z":"7b9046f8e332ea49","name":"","server":"145b1a79.688086","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.battery_consumption_production_diff","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"data2","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":1000,"y":60,"wires":[["f04cc3ddeb847126"]]},{"id":"1f83d96b5aa5a8c1","type":"function","z":"7b9046f8e332ea49","name":"Rocket Launch - Coundtdown","func":"let seconds = Math.floor((Date.parse(msg.data.attributes.launch_target) - Date.now())/1000);\nlet hours = Math.floor(seconds/(60*60),0);\nseconds -= (hours * 60 * 60);\nlet minutes = Math.floor(seconds/60,0);\nseconds -= (minutes * 60);\nlet obj = \n{\n    \"text\": hours + \"h \" + minutes + \"m\", \n    \"icon\": 42127,\n};\nmsg.payload.frames[msg.counter] = obj;\nmsg.counter = msg.counter + 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1110,"y":620,"wires":[["4d833c547c3a9433"]]},{"id":"145b1a79.688086","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30"}]

Besonderheiten:

  • Battery SOC Anzeige: Steuert auch das anzuzeigende Icon
  • Einige Statusabfragen haben Konditionen und werden nur weiterbearbeitet, falls als ein „sinnvoller“ Wert vorhanden.
  • Rocket Launch – Countdown: Berechnet den Zeitpunkt zum Start

In der eigenen LaMetric App setze ich dann auf die URL http://meinhomeassistant:1880/endpoint/meinlametric und eine Aktualisierung alle 30 Sekunden. Bei meiner Integration war zudem noch eine Basic Authentication notwendig.

Dann installiere ich meine eigene App auf der LaMetric und los gehts.