Capture UDP packets with PV production data from Envertech EVT Microinverter and integrate in Home Assistant
Purpose
This Flow captures UDP packets sent from an Envertech EVT800 Microinverter directly to the Node-Red server or container, and converts them to Home Assistant Sensors.
Preparing your Envertech Inverter
This flow directly receives production data from the inverter via regular UDP packets. That means that you will not need to use the Enverview App or the Envertech Web portal. (Note that you can still use the app and the web portal if you want)
Connecting to the Inverter
The inverter exposes a WLAN network named like the inverter's serial number. To connect, the inverter must be connected to PV modules, and it must produce electricity. Take your mobile phone and move close to the inverter, then scan for WLAN networks. You should see a WLAN named exactly like the S/N shown on the sticker on the inverter.
Connect to that WLAN network. Initially, it has now password (which is not really great... more on that later)
Make sure that your phone stays connected. At least Android checks for Internet connectivity and disconnects if there isn't any.
Now use the Web browser on your mobile phone to connect to 10.10.100.254 (that is the default address used on my EVT800) You should be prompted to login. User "admin" both as the username and the password.
Switch to English (unless you can read Chinese...) and select "Other settings" In the lower part of that screen, you can configure a network server that can be used to get PV production data directly from the inverter. My flow assumes that you configure this as follows:
- Protocol: UDP
- Port ID: 14889
- Server Address: (the IP address of your Node-Red server)
You will also have to configure the inverter so that it connects to your own WLAN (otherwise, it will not be able to send any data to your Node-Red server)
Save everything and reboot the inverter. Check your WLAN router or AP and verify that the inverter successfully connects.
Once this is set up correctly, this flow should work right away.
Dependencies
- node-red-contrib-home-assistant-websocket
Improving the security of your EVT800 Microinverter
By default, the EVT800 exposes an unprotected WLAN with a well-known default admin login. For me, that is an absolute no-go. Additionally, the inverter immediately phones home after it starts up. You can decide for yourself, but I neither need nor want that. So, I did the following to make my setup more secure:
- I configured a WLAN password on the inverter's own WLAN -- Please make sure to write this down - there might be a way to reset the inverter to factory defaults, but don't ask me how that is done...
- I configured my internet router to pass a fixed IP address to the inverter, and blocked that IP address from accessing the Internet
[{"id":"c91a4a9ae3e10097","type":"tab","label":"Envertech","disabled":false,"info":"","env":[]},{"id":"5f5fbd560994bef6","type":"udp in","z":"c91a4a9ae3e10097","name":"EVT800","iface":"","port":"14889","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":140,"y":160,"wires":[["242de55d8087e4a4","e1f002177c40d1cc"]],"info":"# Prerequisites\r\nInverter must send PV production data via UDP to the Node-Red server on port 14889"},{"id":"242de55d8087e4a4","type":"switch","z":"c91a4a9ae3e10097","name":"Select long messages","property":"payload.length","propertyType":"msg","rules":[{"t":"gte","v":"84","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":200,"y":280,"wires":[["c70ecd2c4810dca0","9520299440b646c6"]],"info":"The EVT800 appears to send additional shorter packages, which do not contain any PV production data.\r\nThis node discards these packages"},{"id":"1fd05cb39ab3b685","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module 2 power","entityConfig":"2293bac523cca0a1","version":0,"state":"msg.payload.module2_power","stateType":"jsonata","attributes":[{"property":"serial","value":"payload.module2_serial","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":780,"y":460,"wires":[[]]},{"id":"50fb254ef0ad3e38","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module 1 power","entityConfig":"b6489df60b3d183b","version":0,"state":"msg.payload.module1_power","stateType":"jsonata","attributes":[{"property":"serial","value":"payload.module1_serial","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":780,"y":180,"wires":[[]]},{"id":"3058ffe6fb39e9cd","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module 1 total energy","entityConfig":"34a4f3793bde9ac4","version":0,"state":"msg.payload.module1_total_energy","stateType":"jsonata","attributes":[],"inputOverride":"allow","outputProperties":[],"x":800,"y":240,"wires":[[]]},{"id":"e7b6972d14f435ce","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module 2 total energy","entityConfig":"bc6c50b857c7dbf9","version":0,"state":"msg.payload.module2_total_energy","stateType":"jsonata","attributes":[],"inputOverride":"allow","outputProperties":[],"x":800,"y":520,"wires":[[]]},{"id":"952a02548d744d2f","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Total power","entityConfig":"c6318771fe3b3a2f","version":0,"state":"msg.payload.module1_power + msg.payload.module2_power","stateType":"jsonata","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1070,"y":280,"wires":[[]]},{"id":"e1a4afbc8db0e8e5","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Total energy","entityConfig":"887665e724194ef7","version":0,"state":"msg.payload.module1_total_energy+msg.payload.module2_total_energy","stateType":"jsonata","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1070,"y":340,"wires":[[]]},{"id":"c70ecd2c4810dca0","type":"debug","z":"c91a4a9ae3e10097","name":"Raw data","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":240,"wires":[]},{"id":"e1f002177c40d1cc","type":"debug","z":"c91a4a9ae3e10097","name":"Unfiltered data","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":360,"y":120,"wires":[]},{"id":"9520299440b646c6","type":"function","z":"c91a4a9ae3e10097","name":"Calculate counters","func":"var serial = msg.payload.slice(6,10).toString(\"hex\");\nvar serial_module1 = msg.payload.slice(20,24).toString(\"hex\");\nvar serial_module2 = msg.payload.slice(52,56).toString(\"hex\");\n\nvar newmsg = {\n payload: {\n module1_dc_voltage: (msg.payload[26]*0x100+msg.payload[27])/512,\n module1_power: (msg.payload[28]*0x100+msg.payload[29])/64,\n module1_total_energy: (msg.payload[30]*0x1000000+msg.payload[31]*0x10000+msg.payload[32]*0x100+msg.payload[33])/8192,\n module1_temperature: (msg.payload[34]*0x100+msg.payload[35])/128-40,\n module1_ac_voltage: (msg.payload[36]*0x100+msg.payload[37])/64,\n module1_ac_frequency: (msg.payload[38]*0x100+msg.payload[39])/256,\n module2_dc_voltage: (msg.payload[58] * 0x100 + msg.payload[59]) / 512,\n module2_power: (msg.payload[60] * 0x100 + msg.payload[61]) / 64,\n module2_total_energy: (msg.payload[62] * 0x1000000 + msg.payload[63] * 0x10000 + msg.payload[64] * 0x100 + msg.payload[65]) / 8192,\n module2_temperature: (msg.payload[66] * 0x100 + msg.payload[67]) / 128 - 40,\n module2_ac_voltage: (msg.payload[68] * 0x100 + msg.payload[69]) / 64,\n module2_ac_frequency: (msg.payload[70] * 0x100 + msg.payload[71]) / 256,\n inverter_serial: serial,\n module1_serial: serial_module1,\n module2_serial: serial_module2\n }\n}\n\nreturn newmsg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":320,"wires":[["5db67c7dde2e632d","50fb254ef0ad3e38","3058ffe6fb39e9cd","952a02548d744d2f","e1a4afbc8db0e8e5","1fd05cb39ab3b685","e7b6972d14f435ce","be36ecd727cd4161","a54d4662fb68c172","2fb33f0731b55ca2","6ee3ff310fdff458"]],"info":"Extract the binary data from the UDP package and calculate specific values\r\n"},{"id":"5db67c7dde2e632d","type":"debug","z":"c91a4a9ae3e10097","name":"Show calculated values","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":810,"y":580,"wires":[]},{"id":"be36ecd727cd4161","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"inverter_ac_frequency","entityConfig":"0fd8c77150f9f573","version":0,"state":"payload.module1_ac_frequency","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":800,"y":60,"wires":[[]]},{"id":"9b52c89ef8f842f7","type":"comment","z":"c91a4a9ae3e10097","name":"How To setup","info":"# Preparing your Envertech Inverter\nThis flow directly receives production data from the inverter via regular UDP packets.\nThat means that you will not need to use the Enverview App or the Envertech Web portal.\n(Note that you can still use the app and the web portal if you want)\n\n## Connecting to the Inverter\nThe inverter exposes a WLAN network named like the inverter's serial number.\nTo connect, the inverter must be connected to PV modules, and it must produce electricity.\nTake your mobile phone and move close to the inverter, then scan for WLAN networks.\nYou should see a WLAN named exactly like the S/N shown on the sticker on the inverter.\n\nConnect to that WLAN network. Initially, it has now password (which is not really great... more on that later)\n\nMake sure that your phone stays connected. At least Android checks for Internet connectivity and disconnects if there isn't any.\n\nNow use the Web browser on your mobile phone to connect to 10.10.100.254 (that is the default address used on my EVT800)\nYou should be prompted to login. User \"admin\" both as the username and the password.\n\nSwitch to English (unless you can read Chinese...) and select \"Other settings\"\nIn the lower part of that screen, you can configure a network server that can be used to get PV production data directly from the inverter.\nMy flow assumes that you configure this as follows:\n - Protocol: UDP\n - Port ID: 14889\n - Server Address: <the IP address of your Node-Red server>\n \nYou will also have to configure the inverter so that it connects to your own WLAN (otherwise, it will not be able to send any data to your Node-Red server)\n\nSave everything and reboot the inverter. Check your WLAN router or AP and verify that the inverter successfully connects.\n\nOnce this is set up correctly, this flow should work right away.\n\n## Security considerations\nBy default, the EVT800 exposes an unprotected WLAN with a well-known default admin login. For me, that is an absolute no-go.\nAdditionally, the inverter immediately phones home after it starts up. You can decide for yourself, but I neither need nor want that.\nSo, I did the following to make my setup more secure:\n - I configured a WLAN password on the inverter's own WLAN\n -- Please make sure to write this down - there might be a way to reset the inverter to factory defaults, but don't ask me how that is done...\n - I configured my internet router to pass a fixed IP address to the inverter, and blocked that IP address from accessing the Internet\n\n","x":150,"y":60,"wires":[]},{"id":"a54d4662fb68c172","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module1 temperature","entityConfig":"5cf43690e25096c1","version":0,"state":"payload.module1_temperature","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":800,"y":120,"wires":[[]]},{"id":"2fb33f0731b55ca2","type":"ha-sensor","z":"c91a4a9ae3e10097","name":"Module2 temperature","entityConfig":"be1dcc5b20a802fd","version":0,"state":"payload.module2_temperature","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":800,"y":400,"wires":[[]]},{"id":"6ee3ff310fdff458","type":"ha-text","z":"c91a4a9ae3e10097","name":"EVT800 S/N","version":1,"debugenabled":false,"inputs":1,"outputs":1,"entityConfig":"c88d06675e04fb62","exposeAsEntityConfig":"","mode":"set","value":"payload.inverter_serial","valueType":"msg","outputProperties":[],"x":770,"y":640,"wires":[[]]},{"id":"2293bac523cca0a1","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module2.power","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 2 power"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"power"},{"property":"unit_of_measurement","value":"W"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"b6489df60b3d183b","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module1.power","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 1 Power"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"power"},{"property":"unit_of_measurement","value":"W"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"34a4f3793bde9ac4","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module1.total.energy","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 1 Total Energy"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"energy"},{"property":"unit_of_measurement","value":"kWh"},{"property":"state_class","value":"total_increasing"}],"resend":false,"debugEnabled":false},{"id":"bc6c50b857c7dbf9","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module2.total.energy","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 2 Total Energy"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"energy"},{"property":"unit_of_measurement","value":"kWh"},{"property":"state_class","value":"total_increasing"}],"resend":false,"debugEnabled":false},{"id":"c6318771fe3b3a2f","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.evt800.power","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"EVT800 Power"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"power"},{"property":"unit_of_measurement","value":"W"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"887665e724194ef7","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.evt800.energy","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"EVT800 Total Energy"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"energy"},{"property":"unit_of_measurement","value":"kWh"},{"property":"state_class","value":"total_increasing"}],"resend":false,"debugEnabled":false},{"id":"0fd8c77150f9f573","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"ac.frequency","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"AC Frequency"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"frequency"},{"property":"unit_of_measurement","value":"Hz"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"5cf43690e25096c1","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module1.temperature","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 1 temperature"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"temperature"},{"property":"unit_of_measurement","value":"°C"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"be1dcc5b20a802fd","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.module2.temperature","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Module 2 temperature"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"temperature"},{"property":"unit_of_measurement","value":"°C"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"c88d06675e04fb62","type":"ha-entity-config","server":"5065e2ae38ae1cc3","deviceConfig":"59918304925b4a02","name":"sensor.evt800.serial","version":6,"entityType":"text","haConfig":[{"property":"name","value":"EVT800 S/N"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":"diagnostic"},{"property":"mode","value":"text"},{"property":"min_length","value":""},{"property":"max_length","value":""},{"property":"pattern","value":""}],"resend":false,"debugEnabled":false},{"id":"5065e2ae38ae1cc3","type":"server","name":"Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":": ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"default","statusTimeFormat":"h:m","enableGlobalContextStore":false},{"id":"59918304925b4a02","type":"ha-device-config","name":"envertech","hwVersion":"","manufacturer":"Envertech","model":"EVT800","swVersion":""}]