Hoymiles DTU microinverters (PV)

Hi,
I have approached this using nodered and curl command. The solution is much simpler and is stays local (meaning - no need to any passwords, accounts, etc - getting data directly from DTU unit)

Seems like a perfect solution.
Which DTU do you have? For what I’w seen only the Pro one have a integrated web server.
Do you have an installator account, or just a user one?
It looks like we might share the same installation type: three wires, 9kw solar panels, and a huge need to monitor everything.
I’m stuck with a closed-cloud service for the moment (Comwatt, French Cie, crappy spirit…) for the solar monitoring, but would be really happy to change. Your solution seems like a perfect fit.

Hi,

I have DTU-100 (not Pro). I don’t have an installer account BUT - You don’t need any account here as You’re only accessing the web interface of the DTU (on local network).

So, I can simply type in the local url like http://192.168.12.210 and the home page of the DTU is displayed (where all data is displayed). From then on - all I needed to do is get the page contents via http request and parse the results. Most of that is done by nodered. The biggest “trick” in my case was that they use some weird HTPP/0.9 protocol which means that standard GET commands in http requests don’t work…

Anyway - for me, I only need some basic parameters like Total Energy, Total Power, etc. (which are provided in first columns) - but if You play with it You can get data for each panel or whatever You see on the screen (and e.g. create automation for when something is wrong with it).

The IMPORTANT part for mee is that NO INTERNET connection is needed!

I’ve included the code for the NodeRed flow also:

[
    {
        "id": "b52d74e9be54c49b",
        "type": "tab",
        "label": "PV",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "e1ca176c6ebb0e6f",
        "type": "exec",
        "z": "b52d74e9be54c49b",
        "command": "curl 192.168.12.210/hometable.xml --http0.9",
        "addpay": "",
        "append": "",
        "useSpawn": "false",
        "timer": "1",
        "winHide": false,
        "oldrc": false,
        "name": "",
        "x": 370,
        "y": 160,
        "wires": [
            [
                "487410fb842d2664"
            ],
            [
                "4848185b98be45aa"
            ],
            [
                "b31bdde29ea31f7e"
            ]
        ]
    },
    {
        "id": "95773632b7258564",
        "type": "inject",
        "z": "b52d74e9be54c49b",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "60",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "ping",
        "payloadType": "str",
        "x": 110,
        "y": 160,
        "wires": [
            [
                "e1ca176c6ebb0e6f"
            ]
        ]
    },
    {
        "id": "bdb103f2ea61cc72",
        "type": "debug",
        "z": "b52d74e9be54c49b",
        "name": "Debug",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1250,
        "y": 140,
        "wires": []
    },
    {
        "id": "b31bdde29ea31f7e",
        "type": "debug",
        "z": "b52d74e9be54c49b",
        "name": "Return code",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 690,
        "y": 280,
        "wires": []
    },
    {
        "id": "4848185b98be45aa",
        "type": "debug",
        "z": "b52d74e9be54c49b",
        "name": "Errors",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 670,
        "y": 200,
        "wires": []
    },
    {
        "id": "487410fb842d2664",
        "type": "function",
        "z": "b52d74e9be54c49b",
        "name": "Convert to String",
        "func": "msg.payload = msg.payload.toString();\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 670,
        "y": 140,
        "wires": [
            [
                "5b528da2128633eb"
            ]
        ]
    },
    {
        "id": "5b528da2128633eb",
        "type": "csv",
        "z": "b52d74e9be54c49b",
        "name": "Select data",
        "sep": ";",
        "hdrin": false,
        "hdrout": "all",
        "multi": "one",
        "ret": "\\n",
        "temp": "power_total,energy_total,energy_today",
        "skip": "0",
        "strings": true,
        "include_empty_strings": false,
        "include_null_values": false,
        "x": 850,
        "y": 140,
        "wires": [
            [
                "da66d7eb327f9284",
                "0ffdb0c2167f20ce",
                "7749b410bd7be18b"
            ]
        ]
    },
    {
        "id": "da66d7eb327f9284",
        "type": "ha-entity",
        "z": "b52d74e9be54c49b",
        "name": "DTU Energy Today",
        "server": "9847e1812fb1326f",
        "version": 2,
        "debugenabled": false,
        "outputs": 1,
        "entityType": "sensor",
        "config": [
            {
                "property": "name",
                "value": "dtu_energy_today"
            },
            {
                "property": "device_class",
                "value": "energy"
            },
            {
                "property": "icon",
                "value": ""
            },
            {
                "property": "unit_of_measurement",
                "value": "kWh"
            },
            {
                "property": "state_class",
                "value": "total_increasing"
            },
            {
                "property": "last_reset",
                "value": ""
            }
        ],
        "state": "payload.energy_today",
        "stateType": "msg",
        "attributes": [],
        "resend": true,
        "outputLocation": "payload",
        "outputLocationType": "msg",
        "inputOverride": "allow",
        "outputOnStateChange": false,
        "outputPayload": "$entity().state ? \"on\": \"off\"",
        "outputPayloadType": "jsonata",
        "x": 1050,
        "y": 200,
        "wires": [
            [
                "bdb103f2ea61cc72"
            ]
        ]
    },
    {
        "id": "0ffdb0c2167f20ce",
        "type": "ha-entity",
        "z": "b52d74e9be54c49b",
        "name": "DTU Power Total",
        "server": "9847e1812fb1326f",
        "version": 2,
        "debugenabled": false,
        "outputs": 1,
        "entityType": "sensor",
        "config": [
            {
                "property": "name",
                "value": "dtu_power_total"
            },
            {
                "property": "device_class",
                "value": "power"
            },
            {
                "property": "icon",
                "value": ""
            },
            {
                "property": "unit_of_measurement",
                "value": "kW"
            },
            {
                "property": "state_class",
                "value": "measurement"
            },
            {
                "property": "last_reset",
                "value": ""
            }
        ],
        "state": "payload.power_total",
        "stateType": "msg",
        "attributes": [],
        "resend": true,
        "outputLocation": "payload",
        "outputLocationType": "msg",
        "inputOverride": "allow",
        "outputOnStateChange": false,
        "outputPayload": "$entity().state ? \"on\": \"off\"",
        "outputPayloadType": "jsonata",
        "x": 1050,
        "y": 80,
        "wires": [
            [
                "bdb103f2ea61cc72"
            ]
        ]
    },
    {
        "id": "7749b410bd7be18b",
        "type": "ha-entity",
        "z": "b52d74e9be54c49b",
        "name": "DTU Energy Total",
        "server": "9847e1812fb1326f",
        "version": 2,
        "debugenabled": false,
        "outputs": 1,
        "entityType": "sensor",
        "config": [
            {
                "property": "name",
                "value": "dtu_energy_total"
            },
            {
                "property": "device_class",
                "value": "energy"
            },
            {
                "property": "icon",
                "value": "mdi:infinity"
            },
            {
                "property": "unit_of_measurement",
                "value": "kWh"
            },
            {
                "property": "state_class",
                "value": "total_increasing"
            },
            {
                "property": "last_reset",
                "value": ""
            }
        ],
        "state": "payload.energy_total",
        "stateType": "msg",
        "attributes": [],
        "resend": true,
        "outputLocation": "payload",
        "outputLocationType": "msg",
        "inputOverride": "allow",
        "outputOnStateChange": false,
        "outputPayload": "$entity().state ? \"on\": \"off\"",
        "outputPayloadType": "jsonata",
        "x": 1050,
        "y": 140,
        "wires": [
            [
                "bdb103f2ea61cc72"
            ]
        ]
    },
    {
        "id": "9847e1812fb1326f",
        "type": "server",
        "name": "Home Assistant",
        "version": 2,
        "addon": false,
        "rejectUnauthorizedCerts": false,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true,
        "heartbeat": false,
        "heartbeatInterval": "30"
    }
]

Good luck!

Exactly what I need. So you managed to add all the inverters without any account? The gateway I found is the W100, with a USB stick form factor, is that the one?
And do you know then what is the purpose of the pro account?

Anyway, thank you very much for your answers, at least I know that I’ll be able to gather data on my little solar farm.

Hello Papi77
Just received my DTU, but the pro version, just because it was faster. (I’m way too geek to wait!) The W100 (USB stick form factor) should arrive in about 10 days.
Did a company installed your DTU in first place? Or you bought the DTU, and did your own install? Because I have no way to setup my solar installation, or to scan for panels. I can login in the DTU, I have access to the main page of the DTU, but nothing related to the solar installation.
Any clever tip from your side?
Cheers

Well, for those waiting for more informations, I received 2 DTU: the W100 and the Pro. I’m unable to find the DTU-100 Papy77 is using. And so far no luck. I’ve found an installer account to set everything up, but:
The W100 (the usb stick for factor) do not have a local webserver, it only pushes data to the hoymiles website.
The Pro has a local webserver, but only to setup the wifi and a few other settings, but nothing regarding the inverters data.
So pissed that nowadays you have to rely on a cloud solution to access local data.

edit:

Well I’m continuing my monologue in case someone has an idea.
I’m sending back the Pro version, keeping the W100 to feed the cloud (yurk)
I might have found the DTU-100 to follow the Papy77 guidelines, but still waiting for an answer from Netherland. Only shop I found selling it on the web.

I tried to Wireshark the local connection when I access the DTU directly, but absolutely nothing appears, appart DHCP messages. If someone feel like telling me why, or pointing me somewhere…

See you for the next episode

1 Like

If you have DTU-Pro you may give a chance for one of those:

Both of them are using direct ModbusTCP communication to DTU, so the cloud is not needed!

Here also one DTU W100 user trying to get it to communicata to something else than only Hoymiles cloud. The cloud does not have any API, or I cannot find any information of it atleast.

The W100 user interface (web page) looks totally different and it does not tell any data for the user. Only settings can be adjusted. So is there anyone who has found a way to read the data from the W100 module?
The user interface has transfer tab, which defines server settings. I am not good enought with these to say could this be utilized. The SocketA could be something to use?
It looks like this:

I do have a HM-600 - and I am using an ESP32 with an nrf24 module for less than 10€. Flashed them with https://github.com/tbnobody/OpenDTU and imported the data by mqtt into HA.

3 Likes

Hello, about six months ago I made an integration with DTU Pro based on the api of the mobile application.
Using reverse engineering, I developed the communication of the mobile application with DTU and used it to eavesdrop native DTU communication with Hoymiles servers.

At the moment I can confirm 100% stability of operation with data update every minute.
Available here: GitHub - banny310/hoymiles-dtu-homeassistant-addon: Home Assistant Add-on: Hoymiles DTU Solar
Feedback welcome :slight_smile:

2 Likes

Could you explain how you integrated the OpenDTU data?

mqtt:
  sensor:

      - name: "Balkonkraftwerk Leistung AC"
        state_topic: "solar/[serial]/0/power"
        device_class: power
        unit_of_measurement: W
        state_class: measurement
        unique_id: "BalkonkraftwerkLeistungAC"
      - name: "Balkonkraftwerk Module 1-3 Leistung"
        state_topic: "solar/[serial]/1/power"
        device_class: power
        unit_of_measurement: W
        state_class: measurement
        unique_id: "BalkonkraftwerkModule13Leistung"
      - name: "Balkonkraftwerk Module 2-4 Leistung"
        state_topic: "solar/[serial]/2/power"
        device_class: power
        unit_of_measurement: W
        state_class: measurement
        unique_id: "BalkonkraftwerkModule24Leistung"   
      - name: "Balkonkraftwerk Temperatur"
        state_topic: "solar/[serial]/0/temperature"
        device_class: power
        unit_of_measurement: °C
        state_class: measurement
        unique_id: "BalkonkraftwerkTemperatur"
      - name: "Balkonkraftwerk Arbeit Tag"
        state_topic: "solar/[serial]/0/yieldday"
        device_class: energy
        unit_of_measurement: Wh
        state_class: total_increasing
        unique_id: "BalkonkraftwerkArbeitTag"
      - name: "Balkonkraftwerk Arbeit Gesamt"
        state_topic: "solar/[serial]/0/yieldtotal"
        device_class: energy
        unit_of_measurement: kWh
        state_class: total_increasing
        unique_id: "BalkonkraftwerkArbeitGesamt"
1 Like

Can you explain me how this exactly works? In english or german. I own the OpenDTU too, but not very familiar in adding something to homeassistant manually.

You’ll have to configure a mqtt broker like mosquito as addon in homeassistant - and then configure the opendtu to export its data to it.

The string above is for homeassistants configuration to import the data on the mqtt database as sensor.

This tutorial may help you on how to configure the mqtt broker: MQTT Setup | Set up Home Assistant with a Raspberry Pi | Adafruit Learning System

Ok thank you. Do i have to use the inverter oder dtu serial?
Did you change any of the mqtt settings in opendtu? Base Topic or Prefix Topic? Both are homeassistant/ in my openDTU Settings.

I would also be very interested in a tutorial for integrating openDTU into HA, possibly with Grafana. So far I haven’t found anything suitable in my research.

still waiting for help from @eingemaischt :slight_smile:


Got if working now, but it only shows up for about 30seconds to a minute and than it shows “not available”. Its Midnight right now. Does it only show something when the Inverter is working? OpenDTU is running and shows “connected”. I don’t get it.

EDIT:
Somehow that version of @eingemaischt works for me now, but i still have a problem above.

Yes, @Lynsch, the inverter only sends data when it’s working. Otherwise it’s in sleep mode.

I would also be interested if there’s a way to store the sensor data in order to have it displayed in HA during sleep mode.

As people are asking, here is what I did.
Assumption:

  • openDTU up and working and connected to your Wifi
  • MQTT broker up and running in your Wifi
  • HOme Assistant up and running (talking about 2022.10.x - might work with older versions)
  1. Setup MQTT broker in HA
    Add new MQTT integration

  2. Configure openDTU
    – Open webpage from open DTU
    – Goto inverter settings, enter serial number of your converter and give it a name (is used in the sensor name in HA)
    – Goto MQTT settings, enable MQTT, enter your MQTT broker IP address and port (1883?), enter credentials if required
    – check settings again
    – Goto MQTT settings, enable HA auto-discovery

  3. Configure HA dashboards
    – Check MQTT integration under settings - open entities and check if new entities appeared (should). New sensor entities are named “sensor.INVERTERNAME_ATTRIBUTE”
    – Add sensors to your dashboards through any visualization card you want to

  4. If sensor data disappears/expires
    – Goto MQTT settings page
    – disable “Enable expiration” (please note, that this means, the last sensor value stays. You need to monitor reachability of the converter via the according sensor)

I hope this helps…

4 Likes