RPi as Z-Wave/ZigBee-over-IP server for Hass

I have the exact same wish and situation as you have, @tbrasser, but I’ve yet to come to a good enough solution.

I’ve tried usbip for a while, and while it definitely works, it’s a bit of a hassle and requires higher maintenance than I’d like, as well as being very tied to a single machine for the HA container. Also, each restart of HA implies restarting the Z-wave-network as well, which is slow and unpractical. The same argument would apply to socat/ser2net as well, since it relies on software to make a remote serial device in /dev on the machine running the HA instance.

This means, for instance, that I can’t run HA in a container cluster environment, such as Docker Swarm or Kubernetes as I require a local, machine specific resource, that is /dev/tty[something].

I suppose, I could run usbipd in a privileged sidecar container, and as such would be able to run it in a cluster, with the negative point about this solution being running the sidecar as “privileged”, and having to have strict order on container deployment so that I can mount in /dev/tty[something] into the HA container.

I would wish for a Zwave over MQTT solution or similar that actually worked great also for situations as in your “EDIT3”, @tbrasser. I’m not entirely sure how it could be implemented to still take advantage of all the Z-wave features. I think the computer with the Z-wave-stick would run openzwave, and act as a gateway with an API.

I think perhaps that the solution is coming from SiLabs itself, in the form of Z-Wave 700 with Z/IP (Z-wave to IP), as described here: https://www.silabs.com/products/wireless/mesh-networking/z-wave/700-platform/z-wave-700-gateway-development

This is a UDP wrapper for Z-wave command classes, and handles Z-wave network management, security and has a “mailbox” for battery driven devices.

Apparently, we should be able to buy a “Z-Wave 700 Development Kit” (SLWSTK6050A) for a cool USD 379.

Any thoughts?

1 Like

Is anyone using a second HASS instance with just Z-Wave and MQTT Statestream?

Hi

Have you tried making the windows client run again? Any luck?

First of all, nice guide and idea.
Difficult to judge if usbip or the ser2net method is better to be used.

I am reading a lot and planning to have hassio instance dedicated to the wireless receiver (USB dongle)

So my setup will be similar to others.
1.) Hassio running docker on a VM installed on proxmox.
2.) Zwave dongle on a RPi in a more central place of the house.

Yesterday I was almost done with my research about usbip and ser2net and the decision has been made to use usbip.

But then I was reading some more MQTT stuff and found that Zwave to MQTT could be an alternative.

So far I understand the following us needed to use dedicated.
1.) Hassio installed with the standard MQTT in my case on Proxmox
2.) Zwave to Mqtt installed on the RPi with the zwave dongle plugged in.

As far a I understood the inclusion will be done on the RPi and pushed to Hassio automatically.

With MQTT the devices can be read and controlled.

Any thoughts about this idea?
Are you aware of any limitations?

BR Christian

Zwave2Mqtt is what I switched to. A bit more hassle to set every device up (I have several templates for my lock) but by far more stable.

Great to hear you are using it already.

But once again, this means you have Mosquitto as Broker on Hassio and Zwave2Mqtt on your RPi?
Does it mean the inclusion is done on the RPi?
What exactly is more hassle to set every device up`? Is it about the setup in Zwave2MQTT or the way the messages are sent to hass.io?
Highly appreciated if you could get me onboarded :wink:

thx
Chris

Yes. I use the MQTT Community Add-on on my Hass.io machine. and Zwave2Mqtt on my RPi which is by my front door (also a MagicMirror2).

Yes, Zwave2Mqtt has a web interface you use to do all the setup for each device.

After you set each device up on the web interface, HA should pick most of them up with MQTT Discovery, but you may have to manually add/customize some of the MQTT entries for each device in your Hass instance, including any extra attributes you want to track (for me, lock type, user code used, etc.) – all very doable, just not as quick and clean as adding a Z-wave device directly in HA.

Sounds promising;)
I will give this Setup a shot and hope that I am able to handle the mqtt config to hass.io.
Many thanks for your reply.

Last but not least, what do you use for your door to lock/unlock?
I have already a motor build into my doors(24Volt) and so far I plan to use this one:
https://wiki.fhem.de/wiki/DoorPi_und_FHEM
This is a doorpi with some extras originally for FHEM but at the end it would fit for hass.io

AMy main goal is to open my doors by nfc/RFID e.g. a ring on your finger. :slight_smile:

BR Christian

For all those planning to have a similiar setup, “zack” has documented the way towards in a nice manner.

1 Like

Anyone try to make hass.io addon for usbip server/client?

Can we use this: USBIP

I recently updated code for a custom component that had previously used with a local USB device. While troubleshooting the socat connection I realized that I could just simply directly configure a serial-over-ip device in python.

There are a few of these threads, and it really feels like the right solution would to be add in support directly into the zwave components. HA uses a fork of Python-Openzwave, which is actually a wrapper for a C++ library. With that in mind, it might be a bit of a push to actually a remote serial port working directly. Not being well versed in C++ I haven’t jumped down that rabbit hole.

Failing that, a device-proxy could also be a compelling feature. There are many use cases for remote placements of devices attached to raspis or other hostnodes.

P.S. My solution to this for zwave in HA is simple enough, I’ve added a PostStart command to my kubernetes deployment which just starts socat. I’ll wrap it with a watcher scrip mounted in via a ConfigMap soon enough.

apiVersion: apps/v1
kind: StatefulSet
metadata:
   name: homeassistant
   labels:
     app: homeassistant
spec:
  replicas: 1
  serviceName: homeassistant
  selector:
     matchLabels:
       app: homeassistant
  template:
    metadata:
      labels:
        app: homeassistant
    spec:
      containers:
         - name: homeassistant
           image: homeassistant/home-assistant:latest
           lifecycle:
             postStart:
               exec:
                 command: ["sh", "-c", "socat pty,link=/dev/ttyACM0,raw,user=0,group=0,mode=777 tcp:pi-1.example.com:3333 &"]
           env:
             - name: "TZ"
               value: "America/New_York"
...
1 Like

You can also just put hassio/ha on the zigbee/zwave pi and connect them via “home assistant remote”

All devices appear in the master instance automatically and can be used Like local devices.

I’ve been using this setup for a couple of months now and it works great.

2 Likes

I’m trying this approach. So far the devices are not showing up in the master instance. It isn’t a communication problem because sensors do show up. Can you share your config?

I’m looking at setting this up soon, and read in the Github readme that if the master doesn’t have any of the device type added that you’re trying to pull over form the slave, then you’ll need to add the blank domain to your config. So if you’re slave instance has switches, but the master doesn’t, you’ll still need to add switch: without any switches to your configuration.yaml. hope that helps.

Another option I’ve seen, and am debating about using is the usbip linux utility. It passes usb devices from host to client via IP. I’m not sure which would be more reliable.

Thanks I noted that but it wasn’t the issue. In retrospect it may have been that I didn’t do something with ZHA on the VM side.

I’m now using USBIP with my Home Assistant Supervised on a generic Linux host (HASS in Hyper-V) setup. It works! However:
The service was not initializing correctly at reboot on the home assistant side. My first thought was that the issues was it was running the service run before network connections have been established. network-online.target didn’t work but

After=hassio-supervisor.service
Wants=hassio-supervisor.service

Update Not that reliable actually, not sure why this doesn’t always work at startup

Hi my Home Assistant is installed on my ESXI using the VMDK virtual appliance, how do I install “socat” if I make a putty I only have the Home Assistant terminal.

But, when you restart HA from the interface itself only the docker container for homeassistant restarts and not the supervisor service, right? So, socat will not restart when you use this approach and restart from the webinterface, only if you restart supervisor as well?

Assuming you use socat the way I use usbip, yes, correct.
Fortunately I don’t lose wifi connection to my PI ever so I don’t need to do this.
Unfortunately the windows 10 hyper-v host I have Homeassistant on force restarts itself every so often.

So for the last few months I’ve been successfully running home-assistant on x86 machine that was remotely connecting to a z-wave usb stick on a RPi, orchestrated on Kubernetes. (however, if you just want the socat commands, you can just extract it from the kubernetes manifests below)

The new ozw-zwave-mqtt support that’s being added will obsolete this (and I’m so excited about that!), but this recipe may still have use for folks who may want to do this for zigbee or any type of other serial interface on a remote machine.

My configuration:

  • Kubernetes cluster (I’m using k3s+metallb and nfs server for persistent storage).
  • VMs on ESXi running as my normal x86 workers (home-assistant will get scheduled on this)
  • RPi node (with node taints --node-taint rpi=true:NoSchedule --node-taint rpi=true:NoExecute)
  • Aeotec Z-Stick 5 attached to the RPi node

I have three kubernetes deployments

  • zwave-server (this will expose the Z-Stick as a tcp service)
  • zwave-client(this will connect to zwave-server and expose it as a pts device on the k8s node)
  • home-assistant(this will mount the /dev/pts so it can access to the client device)

I’m using nodeSelector to place zwave-server on the RPi, and then colocate zwave-client and home-assistant on the same node. (The reason the zwave-client and home-assistant are two deployments is so that I can run the zwave-client in priviledged mode, and keep home-assistant locked down)

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: hass
  name: zwave-server
spec:
  selector:
    matchLabels:
      app: zwave-server
  replicas: 1
  template:
    metadata:
      labels:
        app: zwave-server
    spec:
      containers:
        - image: paullj1/socat_static:1.7.3.3
          name: socat
          args: 
            #- -dddd
            - -dd
            - tcp-l:8080,reuseaddr,keepalive,nodelay
            - file:$(DEVICE),nonblock,rawer
          env:
            - name: DEVICE
              value: "/dev/ttyACM0"
          ports:
            - containerPort: 8080
          securityContext:
            privileged: true # Implied /dev access
      tolerations:
        - key: "rpi"
          operator: Equal
          value: "true"
      nodeSelector:
        kubernetes.io/hostname: "k3s-agent-rpi3.home"

---
apiVersion: v1
kind: Service
metadata:
  namespace: hass
  name: zwave-server
spec:
  ports:
  - port: 8080
  selector:
    app: zwave-server
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: hass
  name: zwave-client
spec:
  selector:
    matchLabels:
      app: zwave-client
  replicas: 1
  template:
    metadata:
      labels:
        app: zwave-client
    spec:
      containers:
        - image: paullj1/socat_static:1.7.3.3
          name: socat
          args: 
            #- -dddd
            - -dd
            - pty,link=/var/run/zwave/dev,ignoreof,rawer
            - tcp:zwave-server:8080,forever
          securityContext:
            privileged: true # Implied /dev access
          volumeMounts:
            - name: dev-pts
              mountPath: /dev/pts
            - name: zwave-dir
              mountPath: /var/run/zwave
          resources: {}
      volumes:
        - name: dev-pts
          hostPath:
            path: /dev/pts
            type: Directory
        - name: zwave-dir
          hostPath:
            path: /var/run/zwave
            type: DirectoryOrCreate
      nodeSelector:
        kubernetes.io/hostname: "k3s-agent-1.home"
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: hass
  name: hass
spec:
  selector:
    matchLabels:
      app: hass
  replicas: 1
  template:
    metadata:
      labels:
        app: hass
    spec:
      containers:
        - name: hass
          image: homeassistant/home-assistant:0.109.0
          env:
            - name: ZWAVE_DEVICE
              value: /var/run/zwave/dev
          ports:
            - containerPort: 8123
              name: http
              protocol: TCP
          volumeMounts:
            - name: config-nas-volume
              mountPath: /config
            - name: dev-pts
              mountPath: /dev/pts
            - name: zwave-dir
              mountPath: /var/run/zwave
          livenessProbe:
            initialDelaySeconds: 60
            timeoutSeconds: 10
            httpGet:
              path: /api/
              port: http
              httpHeaders:
                - name: Content-Type
                  value: application/json
                - name: Authorization
                  value: Bearer XXXXXXXXXX
          resources: {}
      volumes:
        - name: config-nas-volume
          nfs:
            server: nas.home
            path: /mnt/tank/kubernetes/hass
        - name: zwave-dir
          hostPath:
            path: /var/run/zwave
            type: Directory
        - name: dev-pts
          hostPath:
            path: /dev/pts
            type: Directory
      nodeSelector:
        kubernetes.io/hostname: "k3s-agent-1.home"
---
apiVersion: v1
kind: Service
metadata:
  namespace: hass
  name: hass
spec:
  ports:
  - port: 8123
    targetPort: 8123
    name: hass-8123
  - port: 80
    targetPort: 8123
    name: hass-80
  selector:
    app: hass
  type: LoadBalancer
  loadBalancerIP: XXXXXXXXXXXXX
1 Like