Home assistant and docker swarm

I’ve been trying to get Homeassistant working on swarm for a few months now, but the thing that was preventing me from moving to swarm was the Homeassistant requirement to use host networking on the container.
I had tried many things but I finally got everything to work with the macvlan driver. I configured the homeassistant service with two networks:

  • One macvlan network, giving it an IP address in my iot network
  • One overlay network, giving traefik access to homeassistant

The macvlan network is configured as follows. I had to create a local macvlan network on each member of the swarm, with a subnet swarm is free to choose an IP from:

1st node:
docker network create –config-only –subnet=192.168.2.0/24 –gateway=192.168.2.1 -o parent=eth0 –ip-range 192.168.2.232/29 macvlan_local
2nd node:
docker network create –config-only –subnet=192.168.2.0/24 –gateway=192.168.2.1 -o parent=eth0 –ip-range 192.168.2.240/29 macvlan_local
3rd node:
docker network create –config-only –subnet=192.168.2.0/24 –gateway=192.168.2.1 -o parent=eth0 –ip-range 192.168.2.248/29 macvlan_local

Then I create a swarm scoped network:

docker network create -d macvlan –scope swarm –config-from macvlan_local macvlan_swarm

Then I can deploy the whole stack, here is the docker-compose file:
(the wait-for-it config is a script that prevents homeassistant from starting before mqtt, it’s not necessary but quite useful)

version: '3.7'

configs:
  wait-for-it:
    file: /srv/docker/homeassistant/wait-for-it/wait-for-it.sh

services:
  homeassistant:
    image: homeassistant/armhf-homeassistant:0.86.4
    configs:
      - source: wait-for-it
        target: /wait-for-it.sh
        mode: 755
    networks:
      - webgateway
      - macvlan_swarm
    command: ["/wait-for-it.sh", "rasper:1883", "--", "python", "-m", "homeassistant", "--config", "/config"]
    volumes:
      - /srv/docker/homeassistant/config:/config
      - /etc/localtime:/etc/localtime:ro
    deploy:
      labels:
        - "traefik.backend=hassio"
        - "traefik.frontend.rule=Host:myhomeassistanthostname"
        - "traefik.port=8123"
        - "traefik.enable=true"
        - "traefik.docker.network=webgateway"
        - "traefik.default.protocol=http"

  mosquitto:
    image: eclipse-mosquitto
    volumes:
      - /srv/docker/mosquitto/config:/mosquitto/config
      - /etc/localtime:/etc/localtime:ro
      - /srv/docker/mosquitto/data/mosquitto-data:/mosquitto/data
      - /srv/docker/mosquitto/data/mosquitto-log:/mosquitto/log
    ports:
      - "1883:1883"
      - "9001:9001"

  nodered:
    image: nodered/node-red-docker:rpi-v8
    deploy:
      labels:
        - "traefik.backend=nodered"
        - "traefik.frontend.rule=Host:mynoderedhostname"
        - "traefik.port=1880"
        - "traefik.enable=true"
        - "traefik.docker.network=webgateway"
        - "traefik.default.protocol=http"
    networks:
      - webgateway
    volumes:
      - /srv/docker/nodered:/data
    environment:
      - TZ:Europe/Brussels


volumes:
  mosquitto-data:
  mosquitto-log:

networks:
  webgateway:
    external: true
  macvlan_swarm:
    external: true
  hostnet:
    external: true
    name: host

Home assistant and Unifi Mpower pro

I’ve had a Unifi Mpower pro for a while and I thought it was destined to die forgotten in a closet since UBNT has abandonned it… They are not improving the software anymore, and it’s not really installable at this, plus they have massive security issues with the software controller…

But then I found out that someone had made an MQTT client for this power strip!

I’ve never really worked with MQTT before, but it’s actually quite easy.

First, I installed the software on the power strip, after connecting it to my iot-only wireless network (which doesn’t have internet access. After all, this hardware has no software update, I don’t want to get it into some botnet)

Then I configured it like this:

mqtthost=<ip of my mqtt broker>
topic=homeassistant/mpower1

The power strip publishes to MQTT much information about the state of the plugs.
What I was interested in was the ability to turn them on and off, and to use port1 to monitor our washing machine and alert me when it was finished (when the power usage goes below some value)

To allow me to do that, I defined some sensors to get the power usage of each port, a binary sensor that turns on if the power usage on port1 goes above a fixed value, and some switches to turn everything on or off

So in my configuration.yaml, I have:

sensor:
  - platform: mqtt
    name: "mpower port1 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port1/power"
  - platform: mqtt
    name: "mpower port2 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port2/power"
  - platform: mqtt
    name: "mpower port3 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port3/power"
  - platform: mqtt
    name: "mpower port4 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port4/power"
  - platform: mqtt
    name: "mpower port5 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port5/power"
  - platform: mqtt
    name: "mpower port6 power"
    unit_of_measurement: 'watts'
    state_topic: "homeassistant/mpower1/port6/power"

binary_sensor:
  - platform: template
    sensors:
      washer_state:
        friendly_name: "washer state"
        value_template: >-
          {{ states('sensor.mpower_port1_power')|float > 2 }}

switch:
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port1/relay"
    name: "mpower port1 switch"
    command_topic: "homeassistant/mpower1/port1/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port1/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port2/relay"
    name: "mpower port2 switch"
    command_topic: "homeassistant/mpower1/port2/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port2/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port3/relay"
    name: "mpower port3 switch"
    command_topic: "homeassistant/mpower1/port3/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port3/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port4/relay"
    name: "mpower port4 switch"
    command_topic: "homeassistant/mpower1/port4/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port4/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port5/relay"
    name: "mpower port5 switch"
    command_topic: "homeassistant/mpower1/port5/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port5/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'
  - platform: mqtt
    state_topic: "homeassistant/mpower1/port6/relay"
    name: "mpower port6 switch"
    command_topic: "homeassistant/mpower1/port6/relay/set"
    payload_on: 1
    payload_off: 0
    availability_topic: 'homeassistant/mpower1/port6/lock/$settable'
    payload_available: 'true'
    payload_not_available: 'false'

And in my automations.yaml I have

- id: '1525140123407'
  alias: alert if washer stops
  trigger:
    - platform: state
      entity_id:
        - binary_sensor.washer_state
      from: 'on'
      to: 'off'
  action:
    service: telegram_bot.send_message
    data:
      message: 'washing over'
      target: 123456789

- id: '1525140123408'
  alias: alert if washing starts
  trigger:
    - platform: state
      entity_id:
        - binary_sensor.washer_state
      from: 'off'
      to: 'on'
  action:
    service: telegram_bot.send_message
    data:
      message: 'washing starts'
      target: 123456789