From f3f8ac2b80c0ada56703c80211c87a9d21c56f5b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 11 Jun 2020 11:51:17 +0200 Subject: [PATCH] OpenZWave add-on version 0.4.0 (#1394) Co-authored-by: Martin Hjelmare Co-authored-by: Fabian Affolter --- README.md | 2 +- zwave/CHANGELOG.md | 18 ++- zwave/DOCS.md | 139 +++++++++++++++++- zwave/Dockerfile | 55 +++++-- zwave/README.md | 2 +- zwave/build.json | 5 +- zwave/config.json | 14 +- zwave/icon.png | Bin 0 -> 13154 bytes zwave/logo.png | Bin 0 -> 25857 bytes zwave/rootfs/etc/cont-init.d/network_key.sh | 9 ++ zwave/rootfs/etc/cont-init.d/novnc.sh | 7 + zwave/rootfs/etc/cont-init.d/structure.sh | 1 - zwave/rootfs/etc/services.d/mosquitto/run | 2 +- zwave/rootfs/etc/services.d/ozwadmin/finish | 8 + zwave/rootfs/etc/services.d/ozwadmin/run | 16 ++ zwave/rootfs/etc/services.d/websockify/finish | 8 + zwave/rootfs/etc/services.d/websockify/run | 10 ++ zwave/rootfs/etc/services.d/zwave/discovery | 2 +- zwave/rootfs/etc/services.d/zwave/finish | 2 +- zwave/rootfs/etc/services.d/zwave/run | 25 ++-- 20 files changed, 278 insertions(+), 47 deletions(-) create mode 100644 zwave/icon.png create mode 100644 zwave/logo.png create mode 100644 zwave/rootfs/etc/cont-init.d/network_key.sh create mode 100644 zwave/rootfs/etc/cont-init.d/novnc.sh create mode 100644 zwave/rootfs/etc/services.d/ozwadmin/finish create mode 100644 zwave/rootfs/etc/services.d/ozwadmin/run create mode 100644 zwave/rootfs/etc/services.d/websockify/finish create mode 100644 zwave/rootfs/etc/services.d/websockify/run mode change 100644 => 100755 zwave/rootfs/etc/services.d/zwave/discovery diff --git a/README.md b/README.md index 92d75da..82cb799 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ systems that have installed Home Assistant. TellStick and TellStick Duo service. -- **[OpenZwave](/zwave/README.md)** +- **[OpenZWave](/zwave/README.md)** Allow Home Assistant to talk to a Z-Wave Network via a USB Controller. diff --git a/zwave/CHANGELOG.md b/zwave/CHANGELOG.md index 0e28ed8..503aa61 100644 --- a/zwave/CHANGELOG.md +++ b/zwave/CHANGELOG.md @@ -1,9 +1,25 @@ # Changelog +## 0.4.0 + +- Add OZW instance ID configuration option +- Fix persistent storage of OpenZWave +- Fix permissions on discovery script +- Fix OZW database location +- Improve build speed by using all available cores +- Add built-in ozw-admin +- Add VNC access to add-on to access ozw-admin +- Add Ingress support to add-on to access ozw-admin +- Documentation improvements +- Update OpenZWave (and database) to d2de699 +- Update ozwdaemon to 337e488 +- Add logo and icon +- Detect use of example network key from documentation + ## 0.3.0 - Add port to allow ozw-admin to connect -- Enable discovery again +- Enable discovery again - Set network key default to empty ## 0.2.1 diff --git a/zwave/DOCS.md b/zwave/DOCS.md index effd07f..aaee288 100644 --- a/zwave/DOCS.md +++ b/zwave/DOCS.md @@ -1,40 +1,163 @@ -# Home Assistant Add-on: OpenZwave +# Home Assistant Add-on: OpenZWave ## 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. +2. Find the "OpenZWave" add-on and click it. 3. Click on the "INSTALL" button. +4. This add-on currently requires to have the Mosquitto add-on installed. + Please make sure to install and set up that add-on before continuing. ## How to use +The add-on needs to know where your Z-Wave stick can be found, and therefore, +you'll need to configure the add-on to point to the right device. + +If you're using Home Assistant you may find the correct value for this on the +`Supervisor -> System -> Host system -> Hardware` page. It is recommended +to use a "by-id" path to the device if one exists, as it is not subject to +change if other devices are added to the system. + +1. Replace `null` in the `device` option in the add-on configuration and specify + the device name in quotes: e.g., something like + `"/dev/serial/by-id/usb-0658_0200-if00"`, + `"/dev/ttyUSB0"`, `"/dev/ttyAMA0"`, or `"/dev/ttyACM0"`. +2. Set your 16-byte network key in the form `0x01, 0x02...` used in order to + connect securely to compatible devices. It is recommended that a network key + is configured as security enabled devices may not function correctly if they + are not added securely. +3. Click on "SAVE" to save the add-on configuration. +4. Start the add-on. +5. Add the OpenZWave integration to Home Assistant, see documentation: + + +After installing and starting this add-on, access the ozw-admin interface using +the "OPEN WEBUI" button. + ## Configuration Add-on configuration: ```yaml device: /dev/ttyUSB0 -network_key: +network_key: 0x2e, 0xcc, 0xab, 0x1c, 0xa3, 0x7f, 0x0e, 0xb5, 0x70, 0x71, 0x2d, 0x98, 0x25, 0x43, 0xee, 0x0c instance: 1 ``` ### Option `device` +The device address of your Z-Wave controller. + +If you're using Home Assistant you may find the correct value for this on the +`Supervisor -> System -> Host system -> Hardware` page. It is recommended +to use a "by-id" path to the device if one exists, as it is not subject to +change if other devices are added to the system. + +In most cases this looks like one of the following: + +- `"/dev/serial/by-id/usb-0658_0200-if00"` +- `"/dev/ttyUSB0"` +- `"/dev/ttyAMA0"` +- `"/dev/ttyACM0"` ### Option `network_key` +Security Z-Wave devices require a network key before being added to the network. +You must set the `network_key` configuration option to use a network key before +adding these devices. -### Option `instance` +To generate a network key, you can use the following script in, e.g., the SSH +add-on: -Zwave instance number as reported to MQTT. This corresponds with the +```bash +cat /dev/urandom | tr -dc '0-9A-F' | fold -w 32 | head -n 1 | sed -e 's/\(..\)/0x\1, /g' -e 's/, $//' +``` + +You can also use sites like this one to generate the required data, +just remember to put `0x` before each pair of characters: + + + +Ensure you keep a backup of this key. If you have to rebuild your system and +don't have a backup of this key, you won't be able to reconnect to any security +devices. This may mean you have to do a factory reset on those devices, and your +controller, before rebuilding your Z-Wave network. + +### Option `instance` (optional) + +Z-Wave instance number as reported to MQTT. This corresponds with the `instance_id` attribute of `ozw` services in Home Assistant. +The instance ID defaults to `1`, which is generally fine to keep and use. +Only change this in case you are using multiple instances on the same MQTT +server. + +## Accessing the ozw-admin application + +The add-on allows you to access the underlying ozw-admin application running +in this add-on. This allows you to view, configure and control your Z-Wave +network and its devices. + +### Accessing the ozw-admin application via Ingress + +You can access the built-in ozw-admin application directly via Home Assistant +Ingress. Click on the "OPEN WEBUI" button to access it. + +If it does not auto connect to your Z-Wave network automatically: +Click on the "Open" button in the menu bar of the application and click on +the start button in the **"Remote OZWDaemon"** section. + +If you need to access the application more often, it can be added to the +Home Assistant sidebar by toggling the "Show in sidebar" switch on the +add-on page. + +### Accessing the ozw-admin application via VNC + +You can access the built-in ozw-admin application via a VNC viewer. + +Please note, you can access the same interface using the "OPEN WEBUI" button, +described above. + +To enable it: + +- Set a port number for VNC in the "Network" configuration section of the + add-on and hit "SAVE". Advised is to use port 5900, but any other port above + 5900 works as well. +- Restart the add-on. + +To access it, you need a [VNC Viewer][vnc-viewer] application. If you are using +macOS, you are in luck, since VNC is built-in. Open the spotlight search and +enter the VNC service URL. + +The VNC service URL looks like [vnc://homeassistant.local:5900](vnc-service-url). +Adjust port and possibly hostname if you've changed it in Home Assistant host system +settings. + +### Connecting remotely using a local ozw-admin application + +Alternatively, the ozw-admin application can be downloaded and installed on a +remote machine, like your desktop computer. To connect your remote machine: + +- Set a port number for the ozw-admin in the "Network" configuration section of + the add-on and hit "SAVE". Advised is to use port 1983, as this is the default. +- Restart the add-on. + +To access your Z-Wave network with the ozw-admin, you need to first download the ozw-admin application. The latest +version can be found here: + + + +After you've installed and started the ozw-admin application, click "Open" +and set the remote host and port in the "Remote OZWDaemon" section. +For example, host: `homeassistant.local`, with port `1983` in the second field. + +Next, click on "Start" to connect. ## Known issues and limitations -- You hardware need to be compatible with OpenZwave library +- Your hardware needs to be compatible with OpenZWave library ## Support @@ -48,9 +171,9 @@ You have several options to get them answered: In case you've found a bug, please [open an issue on our GitHub][issue]. - - [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io [issue]: https://github.com/home-assistant/hassio-addons/issues [reddit]: https://reddit.com/r/homeassistant +[vnc-service-url]: vnc://homeassistant.local:5900 +[vnc-viewer]: https://bintray.com/tigervnc/stable/tigervnc/ diff --git a/zwave/Dockerfile b/zwave/Dockerfile index 99dd816..e5de41d 100644 --- a/zwave/Dockerfile +++ b/zwave/Dockerfile @@ -1,67 +1,90 @@ ARG BUILD_FROM FROM ${BUILD_FROM} -# Install QT Open Z-Wave -WORKDIR /usr/src +ENV QT_ASSUME_STDERR_HAS_CONSOLE=1 + ARG OZW_VERSION -ARG QTOZW_VERSION ARG QTMQTT_VERSION +ARG QTOZW_VERSION +ARG QTOZWADMIN_VERSION ARG QTWEBSOCKETS_VERSION +# Install QT Open Z-Wave +WORKDIR /usr/src RUN \ apk add --no-cache \ eudev-libs \ + fontconfig \ + mosquitto \ + openssl \ + pwgen \ qt5-qtbase \ qt5-qtremoteobjects \ - openssl \ - coreutils \ + qt5-qtsvg \ rapidjson \ - mosquitto \ - libcurl \ - pwgen \ + ttf-freefont \ && apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main \ libunwind \ libunwind-dev \ + && apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing \ + novnc \ + websockify \ && apk add --no-cache --virtual .build-dependencies \ + binutils \ build-base \ cmake \ + coreutils \ + curl-dev \ eudev-dev \ git \ + openssl-dev \ qt5-qtbase-dev \ qt5-qtremoteobjects-dev \ - openssl-dev \ + qt5-qtsvg-dev \ rapidjson-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 -j $(( $(nproc) + 1 )) \ && 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 \ + && /usr/lib/qt5/bin/qmake CONFIG+=release QT_BUILD_PARTS="libs tools" \ + && make -j $(( $(nproc) + 1 )) \ && make install \ \ && git clone \ https://github.com/OpenZWave/open-zwave /usr/src/ozw \ && cd /usr/src/ozw \ && git checkout ${OZW_VERSION} \ - && make \ + && make -j $(( $(nproc) + 1 )) \ && 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 \ + && /usr/lib/qt5/bin/qmake -r CONFIG+=release \ + && make -j $(( $(nproc) + 1 )) \ && make install \ \ + && git clone \ + https://github.com/OpenZWave/ozw-admin.git /usr/src/ozw-admin \ + && cd /usr/src/ozw-admin \ + && git checkout ${QTOZWADMIN_VERSION} \ + && /usr/lib/qt5/bin/qmake -r CONFIG+=release \ + && make -j $(( $(nproc) + 1 )) \ + && make install \ + \ + && strip --remove-section=.note.ABI-tag /usr/lib/libQt5Core.so \ + \ + && mkdir -p /usr/share/OpenZWave \ + && mv /usr/share/qt5/qt-openzwavedatabase.rcc /usr/share/OpenZWave/ \ + \ && apk del --no-cache \ .build-dependencies \ libunwind-dev \ diff --git a/zwave/README.md b/zwave/README.md index cea5832..22a7817 100644 --- a/zwave/README.md +++ b/zwave/README.md @@ -1,4 +1,4 @@ -# Home Assistant Add-on: OpenZwave +# Home Assistant Add-on: OpenZWave Allow Home Assistant to talk to a Z-Wave Network via a USB Controller. diff --git a/zwave/build.json b/zwave/build.json index 3db727f..6fb4fb6 100644 --- a/zwave/build.json +++ b/zwave/build.json @@ -7,8 +7,9 @@ "aarch64": "homeassistant/aarch64-base:3.11" }, "args": { - "OZW_VERSION": "1d7f512f3bb9b304fae25fafaf6d3073956b7210", - "QTOZW_VERSION": "41609866979aa3c8da18f4bfb5ffe989675afd8f", + "OZW_VERSION": "d2de6990389888850e936894080e4096c822e379", + "QTOZW_VERSION": "337e48807568e4e7f90d3b8441cc126c9e057cde", + "QTOZWADMIN_VERSION": "18f15f411f9429ba7c5d321329a87f725f22cf7a", "QTMQTT_VERSION": "5.12.8", "QTWEBSOCKETS_VERSION": "5.12.8" } diff --git a/zwave/config.json b/zwave/config.json index 6c13c70..d30d298 100644 --- a/zwave/config.json +++ b/zwave/config.json @@ -1,20 +1,26 @@ { - "name": "OpenZwave", - "version": "0.3.0", + "name": "OpenZWave", + "version": "0.4.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", + "ingress": true, + "ingress_entry": "vnc_lite.html", + "panel_icon": "mdi:z-wave", + "panel_title": "OpenZWave", "startup": "services", "boot": "auto", "init": false, "stage": "experimental", "homeassistant": "0.110.0.dev", "ports": { - "1983/tcp": null + "1983/tcp": null, + "5900/tcp": null }, "ports_description": { - "1983/tcp": "ozw-admin port" + "1983/tcp": "ozw-admin port", + "5900/tcp": "VNC port" }, "services": ["mqtt:want"], "discovery": ["ozw"], diff --git a/zwave/icon.png b/zwave/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..65dfc13893efc395bebfb1458121cc705fa6f2e2 GIT binary patch literal 13154 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 literal 0 HcmV?d00001 diff --git a/zwave/rootfs/etc/cont-init.d/network_key.sh b/zwave/rootfs/etc/cont-init.d/network_key.sh new file mode 100644 index 0000000..7a91ab1 --- /dev/null +++ b/zwave/rootfs/etc/cont-init.d/network_key.sh @@ -0,0 +1,9 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Check to see if example network key from documentation is used +# ============================================================================== +readonly DOCS_EXAMPLE_KEY="0x2e, 0xcc, 0xab, 0x1c, 0xa3, 0x7f, 0x0e, 0xb5, 0x70, 0x71, 0x2d, 0x98, 0x25, 0x43, 0xee, 0x0c" + +if [[ "${DOCS_EXAMPLE_KEY}" == "$(bashio::config 'network_key')" ]]; then + bashio::exit.nok "Network key from the example documentation used. Please create an unique one!" +fi diff --git a/zwave/rootfs/etc/cont-init.d/novnc.sh b/zwave/rootfs/etc/cont-init.d/novnc.sh new file mode 100644 index 0000000..bc2fcb7 --- /dev/null +++ b/zwave/rootfs/etc/cont-init.d/novnc.sh @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Setup noVNC +# ============================================================================== +declare ingress_entry +ingress_entry=$(bashio::addon.ingress_entry) +sed -i "s#websockify#${ingress_entry#?}/websockify#g" /usr/share/novnc/vnc_lite.html diff --git a/zwave/rootfs/etc/cont-init.d/structure.sh b/zwave/rootfs/etc/cont-init.d/structure.sh index 210301f..0f1a09d 100644 --- a/zwave/rootfs/etc/cont-init.d/structure.sh +++ b/zwave/rootfs/etc/cont-init.d/structure.sh @@ -2,5 +2,4 @@ # ============================================================================== # Setup folder structure # ============================================================================== - mkdir -p /data/ozw/config diff --git a/zwave/rootfs/etc/services.d/mosquitto/run b/zwave/rootfs/etc/services.d/mosquitto/run index 9b7bd1d..d4e8fbe 100644 --- a/zwave/rootfs/etc/services.d/mosquitto/run +++ b/zwave/rootfs/etc/services.d/mosquitto/run @@ -2,6 +2,6 @@ # ============================================================================== # Start mosquitto service for communication # ============================================================================== -bashio::log.info "Starting internal mqtt broker..." +bashio::log.info "Starting internal MQTT broker..." exec mosquitto -c /etc/mosquitto.conf diff --git a/zwave/rootfs/etc/services.d/ozwadmin/finish b/zwave/rootfs/etc/services.d/ozwadmin/finish new file mode 100644 index 0000000..698a9da --- /dev/null +++ b/zwave/rootfs/etc/services.d/ozwadmin/finish @@ -0,0 +1,8 @@ +#!/usr/bin/execlineb -S1 +# ============================================================================== +# Take down the S6 supervision tree when ozw-admin 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/ozwadmin/run b/zwave/rootfs/etc/services.d/ozwadmin/run new file mode 100644 index 0000000..bba39be --- /dev/null +++ b/zwave/rootfs/etc/services.d/ozwadmin/run @@ -0,0 +1,16 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Start ozw-admin +# ============================================================================== +OZW_CONFIG=/data/ozw/config + +# Wait until ozw is up and running +bashio::net.wait_for 1983 +bashio::log.info "Starting ozw-admin..." + +cd /data/ozw || bashio::exit.nok "Could not change to OZW working directory" +exec ozwadmin \ + -platform vnc:size=1024x768:port=5900 \ + —-host "localhost:1983" \ + --config-dir "${OZW_CONFIG}" \ + --user-dir "${OZW_CONFIG}" diff --git a/zwave/rootfs/etc/services.d/websockify/finish b/zwave/rootfs/etc/services.d/websockify/finish new file mode 100644 index 0000000..585d778 --- /dev/null +++ b/zwave/rootfs/etc/services.d/websockify/finish @@ -0,0 +1,8 @@ +#!/usr/bin/execlineb -S1 +# ============================================================================== +# Take down the S6 supervision tree when websockify 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/websockify/run b/zwave/rootfs/etc/services.d/websockify/run new file mode 100644 index 0000000..1975096 --- /dev/null +++ b/zwave/rootfs/etc/services.d/websockify/run @@ -0,0 +1,10 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Start ozw-admin +# ============================================================================== + +# Wait until ozwadmin is up and running +bashio::net.wait_for 5900 +bashio::log.info "Starting websockify..." + +exec websockify --web /usr/share/novnc/ 8099 127.0.0.1:5900 diff --git a/zwave/rootfs/etc/services.d/zwave/discovery b/zwave/rootfs/etc/services.d/zwave/discovery old mode 100644 new mode 100755 index 55e278a..f159a8d --- a/zwave/rootfs/etc/services.d/zwave/discovery +++ b/zwave/rootfs/etc/services.d/zwave/discovery @@ -10,7 +10,7 @@ ha_config=$(\ host "$(hostname)" \ port "^1883" \ username "homeassistant" \ - password $(bashio::jq /data/auth.json ".homeassistant_password") \ + password "$(bashio::jq /data/auth.json '.homeassistant_password')" \ ) if bashio::discovery "ozw" "${ha_config}" > /dev/null; then diff --git a/zwave/rootfs/etc/services.d/zwave/finish b/zwave/rootfs/etc/services.d/zwave/finish index 32960a6..20a8bb8 100644 --- a/zwave/rootfs/etc/services.d/zwave/finish +++ b/zwave/rootfs/etc/services.d/zwave/finish @@ -1,6 +1,6 @@ #!/usr/bin/execlineb -S1 # ============================================================================== -# Take down the S6 supervision tree when OpenZwave fails +# Take down the S6 supervision tree when OpenZWave fails # ============================================================================== if { s6-test ${1} -ne 0 } if { s6-test ${1} -ne 256 } diff --git a/zwave/rootfs/etc/services.d/zwave/run b/zwave/rootfs/etc/services.d/zwave/run index 82bccde..b8f42bb 100644 --- a/zwave/rootfs/etc/services.d/zwave/run +++ b/zwave/rootfs/etc/services.d/zwave/run @@ -1,25 +1,30 @@ #!/usr/bin/with-contenv bashio # ============================================================================== -# Start OpenZwave service for zwave radio +# Start OpenZWave service for zwave radio # ============================================================================== -OZW_CONFIG=/data/ozw/config -OZW_NETWORK_KEY=$(bashio::config 'network_key') -OZW_DEVICE=$(bashio::config 'device') -bashio::config.has_value 'instance' \ - && OZW_INSTANCE="$(bashio::config 'instance')" || OZW_INSTANCE=1 +export MQTT_PASSWORD +export OZW_NETWORK_KEY -MQTT_PASSWORD="$(bashio::jq /data/auth.json ".ozw_password")" +MQTT_PASSWORD="$(bashio::jq /data/auth.json '.ozw_password')" +OZW_CONFIG=/data/ozw/config +OZW_DEVICE=$(bashio::config 'device') +OZW_INSTANCE=1 +OZW_NETWORK_KEY=$(bashio::config 'network_key') + +# Set custom instance ID if configured +if bashio::config.has_value 'instance'; then + OZW_INSTANCE=$(bashio::config 'instance') +fi # Wait until mosqitto is up and running -bashio::log.info "Starting OpenZwave..." +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 +cd /data/ozw || bashio::exit.nok "Could not change to OZW working directory" exec ozwdaemon \ -s "${OZW_DEVICE}" \ --config-dir "${OZW_CONFIG}" \