Skip to content

Shelly Pro 3EM: extended documentation with a few hints for Docker and UniFi#172

Draft
MarkusHarmsen wants to merge 1 commit into
sdeigm:mainfrom
MarkusHarmsen:documentation/venus_hints_for_unifi
Draft

Shelly Pro 3EM: extended documentation with a few hints for Docker and UniFi#172
MarkusHarmsen wants to merge 1 commit into
sdeigm:mainfrom
MarkusHarmsen:documentation/venus_hints_for_unifi

Conversation

@MarkusHarmsen

Copy link
Copy Markdown

Hey @sdeigm,

many thanks for your awesome project!

I had a small issue with my Docker and UniFi based home network, where a Marstek Venus was not able to "detect" the virtual Shelly Pro 3EM.

As it might be useful for others in a similar situation, I extended the existing documentation.
If I placed it wrong, please let me know and I will update this PR.

Greetings!

@sdeigm

sdeigm commented Jun 17, 2025

Copy link
Copy Markdown
Owner

Hi Markus, thanks for your input. I think you are right and I should add a separate section which outlines the necessary steps for the different storages. But your comments from above are not 100% correct. I don't have a Marstek storage to test all thinks but from the discussions in the Photovoltaikforum I got the following information:

Initially the Marstek Storage sends out a UDP Broadcast to the local network. Therefore the storage just sets the last octet of its ip address to 255 and assumes that this is the broadcast address. This behavior is only correct for a /24 network type and will not work for all other networks. The first Shelly that answers that broadcast request is "detected" by the Marstek. Afterward, it is a direct communication between the Marstek's and the Shellie's IP address, no UDP broadcast is used anymore. That has the consequence that the Marstek Storage and the Shelly have to be in the same broadcast section of the network for the detection. A lot of switches and even some routers do not forward UDP broadcast request which prevents the detection of the Shelly. But when the initial detection is done, you can move the Shelly/Marstek in different sections of the network, only IP routing between the two is necessary.

For a normal docker installation it is necessary, that the network is in host mode. Otherwise the UDP broadcast traffic is not forwarded into the container. I just tested that in my network with a standard Raspberry Pi and the docker daemon installed with "apt-get install". In bridge mode only my working uni-meter from address 192.168.178.99 answers the UDP broadcast request, there is no answer from the container running in bridge mode on 192.168.178.197:

grafik

When I switch to host networking, I also get an anwer from the docker container on *.197:

grafik

So you either switched to bridge networking mode after the the Marstek had already detected the Shelly and that then worked, or your docker daemon has a specical bridge networking mode, which also forwards UDP broadcast into the container. For a standard docker installation on a Raspberry Pi the host networking mode is necessary for bot the Marstek and the Hoymiles storage (in the detection phase).

@MarkusHarmsen

Copy link
Copy Markdown
Author

Hi sdeigm,

uhhh - interesting insights. Let me verify the current behavior with my Venus E, I definitely don't want to merge wrong assumptions.

My current setup is

  • Raspberry PI (debian bookworm) with docker compose
  • docker inspect -f '{{json .NetworkSettings.Networks }}' uni-meter shows its using the home_docker_default network
  • docker network inspect -f '{{.Driver}}' home_docker_default shows its bridge
  • docker inspect -f '{{json .NetworkSettings.Ports }}' uni-meter shows {"1010/udp":[{"HostIp":"0.0.0.0","HostPort":"1010"},{"HostIp":"::","HostPort":"1010"}]}, so only the single UDP port (IPv4 and IPv6)

But that just means that its NOW bridged. I had it briefly on host when it did not work initially and reverted it after it did not work in the separated "IoT" network -> Its absolutely possible that did not restart when I moved the Venus into the the same network where the Docker Host is running!

Will verify with a sniffer in the evening and come back here.

Greetings

Markus

@sdeigm

sdeigm commented Jun 17, 2025

Copy link
Copy Markdown
Owner

Ok, thanks for verifying again. I used the following docker-compose.yaml file for a the non-working "bridge" case:

services:
  uni-meter:
    image: sdeigm/uni-meter:1.1.11
    container_name: uni-meter
    network_mode: bridge
    restart: unless-stopped
    expose:
      - 80/tcp
      - 5353/udp
      - 1010/udp
    volumes:
      - ./uni-meter.conf:/etc/uni-meter.conf
      - ./logback.xml:/opt/uni-meter/config/logback.xml

When switching to "host", the UDP broadcast package is answered. But your bridge is a "named" bridge which you created with certain parameters I assume. Maybe that's the difference. My "default" bridge has a complete different network address and is a /16 network. The broadcast address here would be 172.17.255.255 total different from my home network where it is 192.168.178.255 which would be used by the Marstek storage:

sdeigm@node-01:~ $ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "3af5f2e3c2aeb147158e2bad73d9348355e005b5e09ce37fbf7e11bd8f5f40f6",
        "Created": "2025-06-11T20:01:59.233049193+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "6eaa2d2bac089863dcfa715bd92b1e542056821608e50b94b2634910c2433b81": {
                "Name": "uni-meter",
                "EndpointID": "615d0460539a2d88258c745c338213b1dcd3103c1c45cf839342b9da55405873",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

@MarkusHarmsen

MarkusHarmsen commented Jun 17, 2025

Copy link
Copy Markdown
Author

Ok, did a super brief check on my Docker Host (the Rasperry PI)

$ sudo tcpdump -n udp port 1010
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:35:45.259304 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
12:35:46.190810 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 422
12:35:46.468671 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
...

It seems you are right, the Venus E is indeed making direct requests and NOT broadcasting anymore!
That explains why I don't need the host network and bridged is fine.

When I now place the Venus E back into my IoT network, it looses the connection. Question for me is now: is it because UPD is not properly routed or does the VENUS not continue with its current behavior if the WIFI / Network changes.

Edit: Routing is working using UDP and all my networks

$ echo '{"id":0,"method":"EM.GetStatus","params":{"id":0}}' | nc -u 192.168.1.1 1010
{"id":0,"src":"shellypro3em-...","result": {...}}

Will try to find out what exactly the Venus is doing and why it looses connection after switching networks.

@MarkusHarmsen MarkusHarmsen marked this pull request as draft June 17, 2025 10:43
@MarkusHarmsen

MarkusHarmsen commented Jun 17, 2025

Copy link
Copy Markdown
Author

Ok, I made an experiment.

As soon as I change the WIFI of my Venus E (Firmware 1.52), it starts to broadcast on UDP port 1010. If it gets a response from any device, it will directly communicate.

Example (using sudo tcpdump -n udp port 1010 on the Raspberry Docker Host):

listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
22:05:01.025314 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
22:05:03.941475 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
22:05:04.853945 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 371
22:05:05.150272 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
22:05:06.618329 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 422
...

the communication is up and running.

When I now keep listening and reconfigure the Venus E to switch WIFI (which is mapped to the 192.168.10.0/24 network):

22:05:44.013650 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
22:05:45.325724 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
22:05:46.535459 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
22:05:49.359617 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
22:05:50.568291 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
22:05:51.777749 IP 192.168.10.162.22222 > 192.168.10.255.1010: UDP, length 50
...

the Venus starts broadcasting, which is not answered by the docker container, no matter if I configure bridged or host. I think it makes sense, as the docker host is on the 192.168.1.0/24 network.

When I now reconfigure the Venus E to switch WIFI again to the original one:

22:06:29.599523 IP 192.168.1.162.22222 > 192.168.1.255.1010: UDP, length 50
22:06:29.637392 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 419
22:06:31.413058 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
22:06:31.573506 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 419
22:06:33.522711 IP 192.168.1.162.22222 > 192.168.1.1.1010: UDP, length 50
22:06:34.073293 IP 192.168.1.1.1010 > 192.168.1.162.22222: UDP, length 419
...

it does first send a broadcast which is now again answered by the container, actually no matter if I configure bridged or host.

This is by the way how I configured the container in docker compose:

  uni-meter:
    image: sdeigm/uni-meter:latest
    container_name: uni-meter
    restart: unless-stopped
    depends_on:
      mqtt:
        condition: service_started
    ports:
      - 1010:1010/udp
    volumes:
      - "./uni_meter/uni-meter.conf:/etc/uni-meter.conf"
      - "./uni_meter/logback.xml:/opt/uni-meter/config/logback.xml"

where I do not use expose and rather directly define the ports

@MarkusHarmsen MarkusHarmsen force-pushed the documentation/venus_hints_for_unifi branch from f67f6f0 to dcc6846 Compare June 17, 2025 20:35
@MarkusHarmsen MarkusHarmsen force-pushed the documentation/venus_hints_for_unifi branch from dcc6846 to c92843e Compare June 17, 2025 20:39
@MarkusHarmsen

MarkusHarmsen commented Jun 17, 2025

Copy link
Copy Markdown
Author

Made an attempt to correct the documentation according to the latest discussion (and actually removed the host/bridged recommendation).

@DanielGlaas

Copy link
Copy Markdown
Contributor

In the docker-compose.yaml, it is defined: network_mode: host

Is this note not automatically fulfilled by network_mode: host?

In a docker setup, make sure forwarding port 1010:1010/udp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants