From 9e18140dd6f638e451e09009bda8e2761d5ec81d Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 7 May 2020 14:12:27 +0200 Subject: [PATCH] Add support for new openzwave (#1273) * Add support for new openzwave * Fix pipeline * fix log output * Support auth / discovery * Add basic structs * fix lint * Fix start order --- deconz/config.json | 2 +- ssh/rootfs/etc/services.d/sshd/finish | 4 +- ssh/rootfs/etc/services.d/ttyd/finish | 4 +- zwave/DOC.md | 20 ++++++ zwave/Dockerfile | 68 ++++++++++++++++++++ zwave/README.md | 38 +++++++++++ zwave/azure-pipelines.yml | 21 ++++++ zwave/build.json | 15 +++++ zwave/config.json | 28 ++++++++ zwave/rootfs/etc/cont-init.d/auth.sh | 33 ++++++++++ zwave/rootfs/etc/cont-init.d/mqtt.sh | 37 +++++++++++ zwave/rootfs/etc/cont-init.d/structure.sh | 6 ++ zwave/rootfs/etc/mosquitto.conf | 20 ++++++ zwave/rootfs/etc/services.d/mosquitto/finish | 8 +++ zwave/rootfs/etc/services.d/mosquitto/run | 7 ++ zwave/rootfs/etc/services.d/zwave/discovery | 20 ++++++ zwave/rootfs/etc/services.d/zwave/finish | 8 +++ zwave/rootfs/etc/services.d/zwave/run | 28 ++++++++ 18 files changed, 362 insertions(+), 5 deletions(-) create mode 100644 zwave/DOC.md create mode 100644 zwave/Dockerfile create mode 100644 zwave/README.md create mode 100644 zwave/azure-pipelines.yml create mode 100644 zwave/build.json create mode 100644 zwave/config.json create mode 100644 zwave/rootfs/etc/cont-init.d/auth.sh create mode 100644 zwave/rootfs/etc/cont-init.d/mqtt.sh create mode 100644 zwave/rootfs/etc/cont-init.d/structure.sh create mode 100644 zwave/rootfs/etc/mosquitto.conf create mode 100644 zwave/rootfs/etc/services.d/mosquitto/finish create mode 100644 zwave/rootfs/etc/services.d/mosquitto/run create mode 100644 zwave/rootfs/etc/services.d/zwave/discovery create mode 100644 zwave/rootfs/etc/services.d/zwave/finish create mode 100644 zwave/rootfs/etc/services.d/zwave/run diff --git a/deconz/config.json b/deconz/config.json index e94b779..b73b6bf 100644 --- a/deconz/config.json +++ b/deconz/config.json @@ -5,7 +5,7 @@ "description": "Control a Zigbee network with ConBee or RaspBee by Dresden Elektronik", "arch": ["amd64", "armhf", "aarch64"], "url": "https://github.com/home-assistant/hassio-addons/tree/master/deconz", - "startup": "system", + "startup": "services", "boot": "auto", "ingress": true, "ingress_entry": "pwa/index.html", diff --git a/ssh/rootfs/etc/services.d/sshd/finish b/ssh/rootfs/etc/services.d/sshd/finish index faf6b31..e5bd8e5 100644 --- a/ssh/rootfs/etc/services.d/sshd/finish +++ b/ssh/rootfs/etc/services.d/sshd/finish @@ -1,8 +1,8 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/execlineb -S1 # ============================================================================== # Take down the S6 supervision tree when sshd fails # ============================================================================== if { s6-test ${1} -ne 0 } if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services \ No newline at end of file +s6-svscanctl -t /var/run/s6/services diff --git a/ssh/rootfs/etc/services.d/ttyd/finish b/ssh/rootfs/etc/services.d/ttyd/finish index aad97ff..2235a70 100644 --- a/ssh/rootfs/etc/services.d/ttyd/finish +++ b/ssh/rootfs/etc/services.d/ttyd/finish @@ -1,8 +1,8 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/execlineb -S1 # ============================================================================== # Take down the S6 supervision tree when ttyd fails # ============================================================================== if { s6-test ${1} -ne 0 } if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services \ No newline at end of file +s6-svscanctl -t /var/run/s6/services diff --git a/zwave/DOC.md b/zwave/DOC.md new file mode 100644 index 0000000..c982f35 --- /dev/null +++ b/zwave/DOC.md @@ -0,0 +1,20 @@ +# How to use + +## Configuration + +Add-on configuration: + +```yaml +device: /dev/ttyUSB0 +network_key: +``` + +### Option `device` + + +### Option `network_key` + + +## Known issues and limitations + +- You hardware need to be compatible with OpenZwave library diff --git a/zwave/Dockerfile b/zwave/Dockerfile new file mode 100644 index 0000000..42d09c0 --- /dev/null +++ b/zwave/Dockerfile @@ -0,0 +1,68 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Install Ada +WORKDIR /usr/src +ARG OZW_VERSION +ARG QTOZW_VERSION +ARG QTMQTT_VERSION +ARG QTWEBSOCKETS_VERSION + +RUN \ + apk add --no-cache \ + eudev-libs \ + qt5-qtbase \ + qt5-qtremoteobjects \ + openssl \ + coreutils \ + rapidjson \ + mosquitto \ + libunwind \ + libcurl \ + pwgen \ + && apk add --no-cache --virtual .build-dependencies \ + build-base \ + cmake \ + eudev-dev \ + git \ + qt5-qtbase-dev \ + qt5-qtremoteobjects-dev \ + openssl-dev \ + rapidjson-dev \ + libunwind-dev \ + curl-dev \ + \ + && git clone --depth 1 -b \ + ${QTWEBSOCKETS_VERSION} https://github.com/qt/qtwebsockets /usr/src/qtwebsockets \ + && cd /usr/src/qtwebsockets \ + && /usr/lib/qt5/bin/qmake QT_BUILD_PARTS="libs tools" \ + && make \ + && make install \ + \ + && git clone --depth 1 -b \ + ${QTMQTT_VERSION} https://github.com/qt/qtmqtt /usr/src/qtmqtt \ + && cd /usr/src/qtmqtt \ + && /usr/lib/qt5/bin/qmake QT_BUILD_PARTS="libs tools" \ + && make \ + && make install \ + \ + && git clone \ + https://github.com/OpenZWave/open-zwave /usr/src/ozw \ + && cd /usr/src/ozw \ + && git checkout ${OZW_VERSION} \ + && make \ + && make install \ + \ + && git clone \ + https://github.com/OpenZWave/qt-openzwave /usr/src/qtozw \ + && cd /usr/src/qtozw \ + && git checkout ${QTOZW_VERSION} \ + && /usr/lib/qt5/bin/qmake \ + && make \ + && make install \ + \ + && apk del --no-cache .build-dependencies \ + && rm -rf /usr/src/* + +WORKDIR / +COPY rootfs / diff --git a/zwave/README.md b/zwave/README.md new file mode 100644 index 0000000..428a568 --- /dev/null +++ b/zwave/README.md @@ -0,0 +1,38 @@ +# Home Assistant Add-on: OpenZwave + +Allow Home Assistant to talk to a Z-Wave Network via a USB Controller. + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] + +## About + + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +2. Find the "OpenZwave" add-on and click it. +3. Click on the "INSTALL" button. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found a bug, please [open an issue on our GitHub][issue]. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg +[issue]: https://github.com/home-assistant/hassio-addons/issues +[reddit]: https://reddit.com/r/homeassistant diff --git a/zwave/azure-pipelines.yml b/zwave/azure-pipelines.yml new file mode 100644 index 0000000..a177747 --- /dev/null +++ b/zwave/azure-pipelines.yml @@ -0,0 +1,21 @@ +# https://dev.azure.com/home-assistant + +trigger: + branches: + include: + - master + paths: + include: + - zwave/* +pr: none + +variables: + - name: versionBuilder + value: "2.0" + - group: docker + +jobs: + - template: /.azure/azp-template-addon.yml + parameters: + addon: "zwave" + arch: "--all" diff --git a/zwave/build.json b/zwave/build.json new file mode 100644 index 0000000..d0c8b09 --- /dev/null +++ b/zwave/build.json @@ -0,0 +1,15 @@ +{ + "build_from": { + "amd64": "homeassistant/amd64-base:3.11", + "i386": "homeassistant/i386-base:3.11", + "armhf": "homeassistant/armhf-base:3.11", + "armv7": "homeassistant/armv7-base:3.11", + "aarch64": "homeassistant/aarch64-base:3.11" + }, + "args": { + "OZW_VERSION": "6289ebb56eca7182638d41dce19a5c3d70c9045b", + "QTOZW_VERSION": "73842d79b6eda5c532d673b53a3861c46abe8e01", + "QTMQTT_VERSION": "5.12.8", + "QTWEBSOCKETS_VERSION": "5.12.8" + } +} diff --git a/zwave/config.json b/zwave/config.json new file mode 100644 index 0000000..675a8fc --- /dev/null +++ b/zwave/config.json @@ -0,0 +1,28 @@ +{ + "name": "OpenZwave", + "version": "0.1.0", + "slug": "zwave", + "description": "Control a ZWave network with Home Assistant", + "arch": ["amd64", "i386", "armhf", "armv7", "aarch64"], + "url": "https://github.com/home-assistant/hassio-addons/tree/master/zwave", + "startup": "services", + "boot": "auto", + "stage": "experimental", + "homeassistant": "0.110.0", + "services": ["want:mqtt"], + "discovery": ["zwave_mqtt"], + "auto_uart": true, + "gpio": true, + "apparmor": false, + "privileged": ["SYS_RAWIO"], + "devices": ["/dev/bus/usb:/dev/bus/usb:rwm", "/dev/mem:/dev/mem:rw"], + "options": { + "device": null, + "network_key": null + }, + "schema": { + "device": "str", + "network_key": "password" + }, + "image": "homeassistant/{arch}-addon-zwave" +} diff --git a/zwave/rootfs/etc/cont-init.d/auth.sh b/zwave/rootfs/etc/cont-init.d/auth.sh new file mode 100644 index 0000000..110917f --- /dev/null +++ b/zwave/rootfs/etc/cont-init.d/auth.sh @@ -0,0 +1,33 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Setup auth data +# ============================================================================== +declare homeassistant_pw +declare ozw_pw + +AUTH_FILE=/data/auth.db + +if bashio::fs.file_exists ${AUTH_FILE}; then + bashio::log.info "Auth database exists" + bashio::exit.ok +fi + +homeassistant_pw="$(pwgen 64 1)" +ozw_pw="$(pwgen 64 1)" + +bashio::log.info "Setup mqtt auth db" + +( + echo "ozw:${ozw_pw}" + echo "homeassistant:${homeassistant_pw}" +) > "${AUTH_FILE}" + +# Encrypt data +mosquitto_passwd -U ${AUTH_FILE} + +config=$(bashio::var.json \ + ozw_password "${ozw_pw}" \ + homeassistant_password "${homeassistant_pw}" \ +) + +echo "$config" > /data/auth.json diff --git a/zwave/rootfs/etc/cont-init.d/mqtt.sh b/zwave/rootfs/etc/cont-init.d/mqtt.sh new file mode 100644 index 0000000..aa06160 --- /dev/null +++ b/zwave/rootfs/etc/cont-init.d/mqtt.sh @@ -0,0 +1,37 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Setup mqtt settings +# ============================================================================== +declare host +declare password +declare port +declare username + +if ! bashio::services.available "mqtt"; then + bashio::log.info "No internal MqTT service found" +else + host=$(bashio::services "mqtt" "host") + password=$(bashio::services "mqtt" "password") + port=$(bashio::services "mqtt" "port") + username=$(bashio::services "mqtt" "username") + + ( + echo "connection main-mqtt" + echo "address ${host}:${port}" + ) >> /etc/mosquitto.conf + + # Need auth? + if bashio::var.has_value "${username}" && bashio::var.has_value "${password}"; then + ( + echo "username ${username}" + echo "password ${password}" + ) >> /etc/mosquitto.conf + fi + + ( + echo "topic OpenZWave/# out" + echo "topic # IN OpenZWave/" + ) >> /etc/mosquitto.conf + + bashio::log.info "Connect to internal MqTT service" +fi diff --git a/zwave/rootfs/etc/cont-init.d/structure.sh b/zwave/rootfs/etc/cont-init.d/structure.sh new file mode 100644 index 0000000..210301f --- /dev/null +++ b/zwave/rootfs/etc/cont-init.d/structure.sh @@ -0,0 +1,6 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Setup folder structure +# ============================================================================== + +mkdir -p /data/ozw/config diff --git a/zwave/rootfs/etc/mosquitto.conf b/zwave/rootfs/etc/mosquitto.conf new file mode 100644 index 0000000..a06add8 --- /dev/null +++ b/zwave/rootfs/etc/mosquitto.conf @@ -0,0 +1,20 @@ +## +# defaults +listener 1883 +user root + +## +# logging +log_dest stdout + +## +# datastore +persistence true +persistence_location /data/ + +## +# auth +allow_anonymous false +password_file /data/auth.db + +# Dynamic config diff --git a/zwave/rootfs/etc/services.d/mosquitto/finish b/zwave/rootfs/etc/services.d/mosquitto/finish new file mode 100644 index 0000000..4c23512 --- /dev/null +++ b/zwave/rootfs/etc/services.d/mosquitto/finish @@ -0,0 +1,8 @@ +#!/usr/bin/execlineb -S1 +# ============================================================================== +# Take down the S6 supervision tree when mosquitto fails +# ============================================================================== +if { s6-test ${1} -ne 0 } +if { s6-test ${1} -ne 256 } + +s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/mosquitto/run b/zwave/rootfs/etc/services.d/mosquitto/run new file mode 100644 index 0000000..9b7bd1d --- /dev/null +++ b/zwave/rootfs/etc/services.d/mosquitto/run @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Start mosquitto service for communication +# ============================================================================== +bashio::log.info "Starting internal mqtt broker..." + +exec mosquitto -c /etc/mosquitto.conf diff --git a/zwave/rootfs/etc/services.d/zwave/discovery b/zwave/rootfs/etc/services.d/zwave/discovery new file mode 100644 index 0000000..1ab159a --- /dev/null +++ b/zwave/rootfs/etc/services.d/zwave/discovery @@ -0,0 +1,20 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Send zwave_mqtt discovery information to Home Assistant +# ============================================================================== +declare ha_config + +# Prepare discovery payload +ha_config=$(\ + bashio::var.json \ + host "$(hostname)" \ + port "^1883" \ + username "homeassistant" \ + password $(bashio::jq /data/auth.json ".homeassistant_password") \ +) + +if bashio::discovery "zwave_mqtt" "${ha_config}" > /dev/null; then + bashio::log.info "Successfully send discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/zwave/rootfs/etc/services.d/zwave/finish b/zwave/rootfs/etc/services.d/zwave/finish new file mode 100644 index 0000000..32960a6 --- /dev/null +++ b/zwave/rootfs/etc/services.d/zwave/finish @@ -0,0 +1,8 @@ +#!/usr/bin/execlineb -S1 +# ============================================================================== +# Take down the S6 supervision tree when OpenZwave fails +# ============================================================================== +if { s6-test ${1} -ne 0 } +if { s6-test ${1} -ne 256 } + +s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/zwave/run b/zwave/rootfs/etc/services.d/zwave/run new file mode 100644 index 0000000..f12e1b8 --- /dev/null +++ b/zwave/rootfs/etc/services.d/zwave/run @@ -0,0 +1,28 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Start OpenZwave service for zwave radio +# ============================================================================== +OZW_CONFIG=/data/ozw/config +OZW_NETWORK_KEY=$(bashio::config 'network_key') +OZW_DEVICE=$(bashio::config 'device') +MQTT_PASSWORD="$(bashio::jq /data/auth.json ".ozw_password")" + +# Wait until mosqitto is up and running +bashio::log.info "Starting OpenZwave..." +bashio::net.wait_for 1883 + +# Send out discovery information to Home Assistant +./discovery & + +# Run daemon +export OZW_NETWORK_KEY +export MQTT_PASSWORD +exec ozwdaemon \ + -s "${OZW_DEVICE}" \ + --config-dir "${OZW_CONFIG}" \ + --user-dir "${OZW_CONFIG}" \ + --mqtt-server 127.0.0.1 \ + --mqtt-port 1883 \ + --mqtt-username ozw \ + --mqtt-instance 1 \ + --stop-on-failure