hm2mqtt 2.4.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,127 +1,222 @@
1
- # hm2mqtt.js
1
+ # hm2mqtt
2
2
 
3
3
  [![mqtt-smarthome](https://img.shields.io/badge/mqtt-smarthome-blue.svg)](https://github.com/mqtt-smarthome/mqtt-smarthome)
4
4
  [![NPM version](https://badge.fury.io/js/hm2mqtt.svg)](http://badge.fury.io/js/hm2mqtt)
5
- [![Dependency Status](https://img.shields.io/gemnasium/hobbyquaker/hm2mqtt.js.svg?maxAge=2592000)](https://gemnasium.com/github.com/hobbyquaker/hm2mqtt.js)
6
- [![Build Status](https://travis-ci.org/hobbyquaker/hm2mqtt.js.svg?branch=master)](https://travis-ci.org/hobbyquaker/hm2mqtt.js)
7
- [![Coverage Status](https://coveralls.io/repos/github/hobbyquaker/hm2mqtt.js/badge.svg?branch=master)](https://coveralls.io/github/hobbyquaker/hm2mqtt.js?branch=master)
8
- [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
9
- [![License][mit-badge]][mit-url]
5
+ [![CI](https://github.com/hobbyquaker/hm2mqtt.js/actions/workflows/ci.yml/badge.svg)](https://github.com/hobbyquaker/hm2mqtt.js/actions/workflows/ci.yml)
6
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](LICENSE)
10
7
 
11
- > Node.js based Interface between Homematic and MQTT
8
+ > Interface between the Homematic CCU and MQTT
12
9
 
13
- Because [hm2mqtt](https://github.com/owagner/hm2mqtt) isn't developed anymore and I don't really like Java I decided to
14
- re-implement this with Node.js
10
+ hm2mqtt connects a Homematic CCU (CCU2/CCU3/RaspberryMatic — BidCos-RF, BidCos-Wired, HmIP-RF,
11
+ virtual devices/groups, CUxD, ReGaHSS variables and programs) to an MQTT broker following the
12
+ [mqtt-smarthome](https://github.com/mqtt-smarthome/mqtt-smarthome) convention. Version 3 is an
13
+ adapter on [mqtt-interfaces-core](https://github.com/hobbyquaker/mqtt-interfaces-core) and a
14
+ drop-in replacement for the `ccu-mqtt` node of
15
+ [node-red-contrib-ccu](https://github.com/rdmtc/node-red-contrib-ccu): same topics, same payloads.
15
16
 
16
- It's kind of the same like the original hm2mqtt, but it supports BINRPC and XMLRPC (hm2mqtt only supports BINRPC), so it
17
- can be used with Homematic IP also. Furthermore it supports Rega variables and programs.
17
+ Contents: [Install](#install) · [Options](#options) · [Topics](#topics) · [Payloads](#payloads) ·
18
+ [Names](#names) · [Home Assistant](#home-assistant) · [Migration](#migration) · [Development](#development)
18
19
 
20
+ ## Install
19
21
 
20
- ### Installation
22
+ Node.js ≥ 20.19. The host must be reachable from the CCU: the interface processes call back on
23
+ `--xmlrpc-port` 2126 (and 2127 for binrpc/CUxD) — open them in the host firewall and, on a CCU
24
+ with the firewall set to _restricted_, allow the host in the CCU's firewall settings.
21
25
 
22
- Prerequisites: [Node.js](https://nodejs.org) 6.0 or higher.
23
-
24
- `npm install -g hm2mqtt`
25
-
26
- I suggest to use [pm2](http://pm2.keymetrics.io/) to manage the hm2mqtt process (start on system boot, manage log files,
27
- ...)
28
-
29
-
30
- ### Command Line Options
31
-
32
- Use `hm2mqtt --help` to get a list of available options. All options can also be set per environment variable (e.g.
33
- setting `HM2MQTT_VERBOSITY=debug` has the same effect as using `--verbosity debug` as commandline parameter).
34
-
35
-
36
- ### Topics
26
+ ```
27
+ npm install -g hm2mqtt
28
+ hm2mqtt -a homematic-ccu3 -u mqtt://broker # foreground
29
+ sudo hm2mqtt --install -n hm -a homematic-ccu3 -u mqtt://broker # systemd service hm2mqtt@hm
30
+ ```
37
31
 
38
- * Events are published on `<name>/status/<channelName>/<datapoint>` (JSON payload, follows
39
- [mqtt-smarthome payload format](https://github.com/mqtt-smarthome/mqtt-smarthome/blob/master/Architecture.md))
40
- * Values can be set via `<name>/set/<channelAddress_or_channelName>/<datapoint>` (can be plain or JSON payload). Example:
41
- `hmip/set/Light_Garage/STATE`,
42
- * Single values from arbitrary Paramsets can be set via
43
- `<name>/param/<channelAddress_or_channelName>/<paramset>/<datapoint>`. Example topic for setting the Mode of an 1st gen
44
- Thermostat HM-CC-TC: `hm/param/Temperatur Hobbyraum Soll/MASTER/MODE_TEMPERATUR_REGULATOR`
45
- * Multiple values at once in arbitrary Paramsets can be set via `
46
- ``<name>/param/<channelAddress_or_channelName>/<paramset>`. The payload has to be a JSON object like e.g.
47
- `{"MODE_TEMPERATURE_REGULATOR":2,"TEMPERATUR_COMFORT_VALUE":24}`.
48
- * Arbitrary RPC methods can be called via `<name>/rpc/<iface>/<command>/<callId>` and respond to `<name>/response/<callId>`
49
- (JSON encoded Array as payload). The callId can be an arbitrary string, its purpose is just to collate the response
50
- to the command. iface can be one of `hmip`, `rfd` or `hs485d`.
32
+ `--install` writes the template unit `/etc/systemd/system/hm2mqtt@.service`, the instance
33
+ config `/etc/hm2mqtt/hm.env` (every option as `HM2MQTT_*`) and uses `/var/lib/hm2mqtt/hm/` as
34
+ state directory; broker credentials can live in the shared `/etc/mqtt-interfaces/broker.env`.
35
+ `--uninstall -n hm` removes the instance. `--config-schema` prints a JSON schema of all options
36
+ (management UIs like [she](https://github.com/hobbyquaker/she) build their config forms from it).
51
37
 
38
+ Docker (build from the Dockerfile — no published image yet):
52
39
 
53
- ### Device and Channel Names
40
+ ```
41
+ docker build -t hm2mqtt .
42
+ docker run -d --name hm2mqtt --network host -v hm2mqtt:/data \
43
+ -e HM2MQTT_CCU_ADDRESS=homematic-ccu3 -e HM2MQTT_MQTT_URL=mqtt://broker hm2mqtt
44
+ ```
54
45
 
55
- Device and Channel names are queried from ReGa, this can be disabled by setting the `--disable-rega` option. To trigger
56
- a re-read after changes on the ReGa you can publish a message to `<name>/command/regasync` or just restart hm2mqtt.
57
- As an alternative to using the names from ReGa you can also supply a json file with the `--json-name-table` option
58
- containing address to name mappings, created by e.g.
59
- [homematic-manager](https://github.com/hobbyquaker/homematic-manager). This file should look like:
60
- ```javascript
46
+ Host networking, or publish 2126/2127 and set `HM2MQTT_INIT_ADDRESS` to the docker host's address
47
+ so the CCU can call back. `--restart unless-stopped` brings it back after `maintenance/set/restart`.
48
+
49
+ ## Options
50
+
51
+ `hm2mqtt --help` lists everything; every option is also an environment variable
52
+ `HM2MQTT_<OPTION>` (e.g. `HM2MQTT_CCU_ADDRESS`), plus the unprefixed `MQTT_URL`, `MQTT_USERNAME`,
53
+ `MQTT_PASSWORD`, `MQTT_TLS_CA` as fallback. Precedence: command line > environment > defaults.
54
+
55
+ | option | default | description |
56
+ | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
57
+ | `-a, --ccu-address` | — | hostname or ip of the CCU (required) |
58
+ | `--ccu-tls`, `--ccu-insecure`, `--ccu-username`, `--ccu-password` | off | TLS ports (42001, 42010, …, ReGa 48181) and authentication of a CCU with the firewall/auth enabled |
59
+ | `-i, --interfaces` | `BidCos-RF,HmIP-RF,VirtualDevices,BidCos-Wired` | interfaces to subscribe to (`CUxD` opt-in), or `auto` to probe the ports |
60
+ | `--bidcos-binrpc` | off | binrpc instead of xmlrpc for BidCos-RF/-Wired (CCU2, Homegear; a CCU3 proxies xmlrpc only) |
61
+ | `-l, --listen-address`, `--init-address`, `--xmlrpc-port`, `--binrpc-port` | first ipv4, =listen, 2126, 2127 | callback servers the CCU pushes events to; `--init-address` when the CCU sees another address (NAT, Docker) |
62
+ | `--ping-timeout` | 60 | seconds without an event before a ping, twice that before a re-init (HmIP-RF uses 600) |
63
+ | `--rega` / `--no-rega` | on | names, rooms, functions, variables and programs from the ReGaHSS |
64
+ | `--rega-poll-interval`, `--rega-poll-trigger` | 30, — | variable/program poll interval (0 = off) and an optional `channel.datapoint` (virtual button) that triggers a poll |
65
+ | `--ccu-timezone` | host | IANA time zone of the CCU, for the timestamps of variables and cached values |
66
+ | `-m, --name-file` | — | JSON `{address: name}` overriding ReGa names ([example-names.json](example-names.json)) |
67
+ | `--item-template`, `--sysvar-item-template`, `--program-item-template` | `${channelName\|channel}/${datapoint}`, `${name}` | how items (topic parts) are built, see [Item templates](#item-templates) |
68
+ | `--rega-names-interval` | 3600 | seconds between re-reads of names/rooms/functions (0 = only at start and on `set/rega/sync`) |
69
+ | `--hm-payload` / `--no-hm-payload` | on | the `hm` meta data block in status payloads ([Payloads](#payloads)) |
70
+ | `--plain-tree <level>` | — | additionally publish plain payloads under `<name>/<level>/…` (the second `ccu-mqtt` node of the Node-RED flow) |
71
+ | `--publish-cache` | off | publish every datapoint value known to the ReGa at start (thousands of retained messages) |
72
+ | `--publish-counters`, `--duty-cycle-interval` | on, 90 | rpc rx/tx counters and `listBidcosInterfaces` duty cycle polling (0 = off) |
73
+ | `--rpc-topics` | off | arbitrary rpc calls via MQTT — an unrestricted API surface, only on a trusted broker |
74
+ | `--state-dir` | `$STATE_DIRECTORY` or `~/.hm2mqtt` | devices, paramset descriptions, names and last values |
75
+ | `-u, --mqtt-url`, `--mqtt-username`, `--mqtt-password`, `--mqtt-tls-ca`, `-n, --name`, `--json-payloads`, `--maintenance`, `-v, --verbosity` | core | shared options of every adapter; `--name` (default `hm`) is the topic prefix |
76
+
77
+ ## Topics
78
+
79
+ `<name>` = `--name` (default `hm`). Channel and variable names are the CCU's, verbatim (spaces,
80
+ umlauts and `/` included; `+`, `#` and empty levels become `_`).
81
+
82
+ | topic | direction | payload |
83
+ | ----------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
84
+ | `<name>/connected` | out | `0` gone, `1` broker connected, `2` every interface subscribed and the ReGa answering (retained) |
85
+ | `<name>/status/<channel>/<DATAPOINT>` | out | every event, retained except `PRESS_*` and other `ACTION` datapoints |
86
+ | `<name>/status/<channel>/LEVEL_NOTWORKING`, `…/STATE_NOTWORKING` | out | the value of an actuator once it stopped moving/dimming (for UI sliders) |
87
+ | `<name>/status/<variable>`, `<name>/status/<program>` | out | variables and programs (`val` = value / active), on change and at start |
88
+ | `<name>/status/interface/<interface>/connected` | out | `true`/`false` per interface process |
89
+ | `<name>/status/counter/<interface>/rx`, `…/tx` | out | received event batches / sent setValue+putParamset calls since start |
90
+ | `<name>/status/<interfaceAddress>/DUTY_CYCLE` | out | duty cycle of every RF adapter (`listBidcosInterfaces`), plus `CARRIER_SENSE_LEVEL` and `CONNECTED` where reported |
91
+ | `<name>/info` | out | adapter, version, `ccu`, `interfaces`, `devices` (retained) |
92
+ | `<name>/set/<channelNameOrAddress>/<DATAPOINT>` | in | plain value or `{"val": …}`; cast by the paramset description (booleans, `ENUM` names, floats) |
93
+ | `<name>/set/<variable>` | in | value; `ENUM` names accepted |
94
+ | `<name>/set/<program>` | in | `true`/`false` activates/deactivates, anything else (e.g. `start`) executes the program |
95
+ | `<name>/set/rega/sync` | in | re-read names, rooms and functions after changes on the CCU |
96
+ | `<name>/paramset/<channelOrDevice>/<PARAMSET>` | in | JSON object → `putParamset`, e.g. `{"MODE_TEMPERATUR_REGULATOR": 2}` on `MASTER` |
97
+ | `<name>/paramset/<channelOrDevice>/<PARAMSET>/<PARAM>` | in | single value → `putParamset` |
98
+ | `<name>/rpc/<interface>/<method>/<callId>` → `<name>/response/<callId>` | in/out | `--rpc-topics` only: JSON array of parameters, answer as JSON (or `{"error": …}`) |
99
+ | `<name>/maintenance/set/loglevel`, `…/restart` | in | `error`/`warn`/`info`/`debug`; graceful restart (core, `--no-maintenance` disables) |
100
+
101
+ ### Item templates
102
+
103
+ The part after `status/` and `set/` (the _item_) is rendered from a template with the fields of the
104
+ `hm` block as placeholders, like node-red-contrib-ccu's topic templates — `--item-template`
105
+ (default `${channelName|channel}/${datapoint}`), `--sysvar-item-template` and
106
+ `--program-item-template` (default `${name}`). `|` is a fallback chain, field names are
107
+ case-insensitive, an empty result becomes `_`. Examples: `${device}/${channelIndex}/${datapoint}`
108
+ (addresses only), `${room|_}/${channelName}/${datapoint}`, `${iface}/${channel}/${datapoint}`,
109
+ `sysvar/${name}`. `set` topics are resolved through a reverse index of every known channel and
110
+ datapoint (the address form `<address>/<DATAPOINT>` always works too); channels rendering the same
111
+ item are listed at start, the first one wins.
112
+
113
+ Use the channel name (`Licht Küche`) or the address (`OEQ1234567:1`) in `set` and `paramset`
114
+ topics. `set/<channel>/<DATAPOINT>` with two channels sharing a name reaches the first one — the
115
+ start-up log lists duplicate names.
116
+
117
+ ## Payloads
118
+
119
+ Status payloads are JSON: `{"val": …, "ts": <ms>, "lc": <ms>, "hm": {…}}` — `val` the value,
120
+ `ts` the time of the event (variables: the CCU's timestamp), `lc` the last change. `hm` is the
121
+ meta data block of node-red-contrib-ccu's messages, field for field:
122
+
123
+ ```json
61
124
  {
62
- "EEQ1234567": "Device Name",
63
- "EEQ1234567:1": "Channel Name",
64
- ...
125
+ "val": 0.5,
126
+ "ts": 1787900000000,
127
+ "lc": 1787899000000,
128
+ "hm": {
129
+ "ccu": "homematic-ccu3",
130
+ "iface": "BidCos-RF",
131
+ "device": "OEQ1234567",
132
+ "deviceName": "Dimmer Flur",
133
+ "deviceType": "HM-LC-Dim1L-CV",
134
+ "channel": "OEQ1234567:1",
135
+ "channelName": "Licht Flur",
136
+ "channelType": "DIMMER",
137
+ "channelIndex": 1,
138
+ "datapoint": "LEVEL",
139
+ "datapointName": "BidCos-RF.OEQ1234567:1.LEVEL",
140
+ "datapointType": "FLOAT",
141
+ "datapointMin": 0,
142
+ "datapointMax": 1,
143
+ "datapointDefault": 0,
144
+ "datapointControl": "DIMMER.LEVEL",
145
+ "datapointUnit": "100%",
146
+ "valuePrevious": 0.3,
147
+ "valueStable": 0.5,
148
+ "rooms": ["Flur"],
149
+ "room": "Flur",
150
+ "functions": ["Licht"],
151
+ "function": "Licht",
152
+ "ts": 1787900000000,
153
+ "tsPrevious": 1787899000000,
154
+ "lc": 1787899000000,
155
+ "change": true,
156
+ "cache": false,
157
+ "uncertain": false,
158
+ "working": false,
159
+ "direction": 0,
160
+ "stable": true
161
+ }
65
162
  }
66
163
  ```
67
164
 
165
+ `ENUM` datapoints carry `datapointEnum` (the value list) and `valueEnum` (the name of the current
166
+ value). Variables have `type: "SYSVAR"` with `valueType`, `unit`, `enum`, `valueEnum`, `id` and —
167
+ when bound to a channel — the channel fields; programs `type: "PROGRAM"` with `active`,
168
+ `activePrevious`, `ts` (last execution). `--no-hm-payload` leaves `{val, ts, lc}`,
169
+ `--no-json-payloads` publishes the bare value. `--plain-tree state` mirrors every item to
170
+ `<name>/state/…` with plain values and booleans as `0`/`1`.
68
171
 
69
- ### ReGa (Homematic variables and programs)
172
+ ## Names
70
173
 
71
- To receive changes from ReGa you have to set `--rega-poll-interval` and/or `--rega-poll-trigger`.
72
- `--rega-poll-trigger` can be set to e.g. `BidCoS-RF:50.PRESS_SHORT`, then a polling is done whenever this virtual button
73
- is pressed. This is meant to create a "pseudo push mechanism" where a program on the ccu reacts on variable changes and
74
- presses this virtual button.
174
+ Names come from the ReGa (devices, channels, rooms, functions), are cached in the state
175
+ directory and re-read with `<name>/set/rega/sync`. A `--name-file` overrides single addresses.
176
+ Without the ReGa (`--no-rega`) topics use addresses. Events of channels without a name use the
177
+ address as well.
75
178
 
76
- Variables and Programs are published to `<name>/status/<variableOrProgramName>` and can be set by sending a message to
77
- `<name>/rega/<variableOrProgramName>`. Publishing `true` or `false` to a program activates/deactivates the program. To
78
- start a program publish the string `start`.
179
+ ## Home Assistant
79
180
 
181
+ The core's discovery options (`--ha-discovery`, `--ha-prefix`) exist, but 3.0 does not announce
182
+ devices yet — channel-type to entity mapping is planned for 3.1 (ROADMAP §10).
80
183
 
81
- ### _NOTWORKING datapoints
184
+ ## Migration
82
185
 
83
- hm2mqtt sends virtual datapoints named `LEVEL_NOTWORKING` respectively `STATE_NOTWORKING` for actuators that have a
84
- `WORKING` and/or `DIRECTION` datapoint. The `*_NOTWORKING` datapoints are only updated when `WORKING` is `false` - this
85
- is useful for e.g. sliders in a UI to prevent jumping sliders when a Blind or Keymatic is moving or a Dimmer is dimming.
186
+ ### From the node-red-contrib-ccu `ccu-mqtt` flow
86
187
 
188
+ Same topics for events, variables, programs, counters, `set` and `paramset`. Differences:
87
189
 
88
- ## docker image for hm2mqtt.js
190
+ - `<name>/connected` reflects the CCU: `1` while an interface is down (the flow always said `2`).
191
+ - `hm.ccu` is the configured `--ccu-address` (the flow, running on the CCU, said `localhost`).
192
+ - Counters and duty cycle payloads are `{val, ts, lc}` like every other status (`val` unchanged).
193
+ - `PRESS_*` **and** other `ACTION` datapoints are not retained.
194
+ - Variables and programs are published at start too, not only on change; polling is on by default.
195
+ - `hm` carries `datapointEnum`/`valueEnum` (from the `VALUE_LIST`) and `datapointUnit`.
196
+ - `paramset` values are cast by their own description and rejected when not writeable.
197
+ - The second (plain) `ccu-mqtt` node is `--plain-tree state`; the `rpc` topic of the node never
198
+ worked — `--rpc-topics` brings the 2.x form back.
89
199
 
90
- #### Usage (architecture: amd64)
91
- - pull the image to your machine, or if you are on a swarm to each node
92
- ```
93
- docker pull mqttsmarthome/hm2mqtt:latest
94
- ```
95
- - start the container with (e.g)
96
- ```
97
- docker run -d -p 2126:2126 -p 2127:2127 --name hm2mqtt -e HM2MQTT_MQTT-URL="mqtt://xxx.xxx.xxx.xxx" -e HM2MQTT_MQTT-USERNAME="mqtt-user-name" -e HM2MQTT_MQTT-PASSWORD="mqtt-user-password" -e HM2MQTT_CCU-ADDRESS="xxx.xxx.xxx.xxx" -e HM2MQTT_INIT-ADDRESS="xxx.xxx.xxx.xxx" -e HM2MQTT_VERBOSITY="debug" mqttsmarthome/hm2mqtt
98
- ```
99
- - or the service in your swarm with (e.g)
100
- ```
101
- docker service create --name hm2mqtt \
102
- --network ingress \
103
- --publish 2126:2126 \
104
- --publish 2127:2127 \
105
- --env HM2MQTT_MQTT-URL="mqtt://xxx.xxx.xxx.xxx" \
106
- --env HM2MQTT_MQTT-USERNAME="mqtt-user-name" \
107
- --env HM2MQTT_MQTT-PASSWORD="mqtt-user-password" \
108
- --env HM2MQTT_CCU-ADDRESS="xxx.xxx.xxx.xxx" \
109
- --env HM2MQTT_INIT-ADDRESS="xxx.xxx.xxx.xxx" \
110
- --env HM2MQTT_VERBOSITY="debug" \
111
- mqttsmarthome/hm2mqtt
112
- ```
200
+ ### From hm2mqtt 2.x
113
201
 
114
- #### Usage (architecture: armhf)
115
- - pull the image to your machine, or if you are on a swarm to each node
116
- ```
117
- docker pull mqttsmarthome/hm2mqtt:armhf
118
- ```
119
- - follow the description above (architecture: amd64), but leave out the pull sequence mentioned there.
202
+ | 2.x | 3.0 |
203
+ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
204
+ | `hm/status/<ch>/<dp>` with `hm: {ADDRESS, UNIT, ENUM}` | same topic, `hm` block as above (`channel`, `datapointUnit`, `valueEnum`) |
205
+ | `hm/rega/<variable\|program>` | `hm/set/<variable\|program>` |
206
+ | `hm/param/<ch>/<paramset>/<dp>` | `hm/paramset/<ch>/<paramset>/<param>` |
207
+ | `hm/rpc/<rfd\|hmip\|hs485d>/<method>/<callid>` | `hm/rpc/<BidCos-RF\|HmIP-RF\|BidCos-Wired\|…>/<method>/<callid>` (`--rpc-topics`) |
208
+ | `hm/command/regasync` | `hm/set/rega/sync` |
209
+ | `hm/status/counter/<rfd\|hmip>/rpc/<rx\|tx>` | `hm/status/counter/<BidCos-RF\|HmIP-RF>/<rx\|tx>` |
210
+ | `db/extend/hm/<address>` (`--publish-metadata`) | dropped |
211
+ | `--insecure`, `--disable-rega`, `--json-name-table`, `--mqtt-retain` | `--ccu-insecure` / `--mqtt-tls-ca`, `--no-rega`, `--name-file`, — |
212
+ | interface names `rfd`, `hmip`, `hs485d` | `BidCos-RF`, `HmIP-RF`, `BidCos-Wired` |
120
213
 
214
+ ## Development
121
215
 
122
- ## License
216
+ `npm test` (node:test, no CCU needed), `npm run lint`. `deploy.sh` ships the package (and
217
+ `file:../` siblings) to a host and restarts the `hm2mqtt@*` units. Plan and decisions:
218
+ [ROADMAP.md](ROADMAP.md); changes: [CHANGELOG.md](CHANGELOG.md).
123
219
 
124
- MIT (c) 2017 [Sebastian Raff](https://github.com/hobbyquaker)
220
+ ## License
125
221
 
126
- [mit-badge]: https://img.shields.io/badge/License-MIT-blue.svg?style=flat
127
- [mit-url]: LICENSE
222
+ MIT (c) Sebastian Raff
package/config.js CHANGED
@@ -1,59 +1,113 @@
1
- const pkg = require('./package.json');
1
+ import {parseConfig} from 'mqtt-interfaces-core';
2
+ import pkg from './package.json' with {type: 'json'};
3
+ import {DEFAULT_INTERFACES, INTERFACE_NAMES} from './lib/interfaces.js';
4
+ import {DEFAULT_ITEM_TEMPLATE, DEFAULT_SYSVAR_ITEM_TEMPLATE, DEFAULT_PROGRAM_ITEM_TEMPLATE} from './lib/topics.js';
2
5
 
3
- module.exports = require('yargs')
4
- .env('HM2MQTT')
5
- .usage(pkg.name + ' ' + pkg.version + '\n' + pkg.description + '\n\nUsage: $0 [options]')
6
- .describe('verbosity', 'possible values: "error", "warn", "info", "debug"')
7
- .describe('name', 'instance name. used as mqtt client id and as prefix for connected topic')
8
- .describe('mqtt-url', 'mqtt broker url. See https://github.com/mqttjs/MQTT.js#connect-using-a-url')
9
- .describe('mqtt-username', 'mqtt broker username')
10
- .describe('mqtt-password', 'mqtt broker password')
11
- .describe('ping-interval', 'Send a Ping if no event occured in the last interval. Re-Init on next interval')
12
- .describe('disable-rega', 'Don\'t sync names from ReGa')
13
- .describe('json-name-table', 'A JSON file that maps device and channel addresses to names')
14
- .describe('rega-poll-interval', 'Interval in seconds to poll variables from Rega. Set to 0 to disable polling')
15
- .describe('rega-poll-trigger', 'A virtual button that triggers a variable poll. Example: BidCoS-RF:50.PRESS_SHORT')
16
- .describe('listen-address', 'Address the RPC servers bind to')
17
- .describe('init-address', 'Address used in the RPC init. Normally there is no need to set this')
18
- .describe('help', 'show help')
19
- .describe('publish-metadata', '')
20
- .describe('mqtt-retain', 'enable/disable retain flag for mqtt messages')
21
- .alias({
22
- a: 'ccu-address',
23
- b: 'binrpc-listen-port',
24
- d: 'disable-rega',
25
- h: 'help',
26
- i: 'ping-interval',
27
- j: 'json-name-table',
28
- l: 'listen-port',
29
- m: 'mqtt-url',
30
- n: 'name',
31
- p: 'mqtt-password',
32
- q: 'hmip-reconnect-interval',
33
- r: 'listen-address',
34
- s: 'init-address',
35
- u: 'mqtt-username',
36
- v: 'verbosity'
37
- })
38
- .boolean('mqtt-retain')
39
- .default({
40
- 'disable-rega': false,
41
- 'mqtt-url': 'mqtt://127.0.0.1',
42
- name: 'hm',
43
- verbosity: 'info',
44
- 'listen-address': require('./firstip.js'),
45
- 'listen-port': 2126,
46
- 'binrpc-listen-port': 2127,
47
- 'ping-interval': 30,
48
- 'hmip-reconnect-interval': 600,
49
- 'rega-poll-interval': 0,
50
- 'rega-poll-trigger': '',
51
- 'publish-metadata': false,
52
- 'mqtt-retain': true
53
- })
54
- .demandOption([
55
- 'ccu-address'
56
- ])
57
- .version()
58
- .help('help')
59
- .argv;
6
+ export const OPTIONS = {
7
+ 'ccu-address': {alias: 'a', type: 'string', describe: 'hostname or ip of the CCU', demandOption: true},
8
+ 'ccu-tls': {type: 'boolean', describe: 'use the TLS ports (4xxxx) and https for ReGa', default: false},
9
+ 'ccu-insecure': {type: 'boolean', describe: "accept the CCU's self-signed certificate", default: false},
10
+ 'ccu-username': {type: 'string', describe: 'CCU user (authentication enabled on the CCU)'},
11
+ 'ccu-password': {type: 'string', describe: 'CCU password', secret: true},
12
+ interfaces: {
13
+ alias: 'i',
14
+ type: 'string',
15
+ describe: `comma separated interfaces (${INTERFACE_NAMES.join(', ')}) or "auto" (probe the ports)`,
16
+ default: DEFAULT_INTERFACES.join(','),
17
+ },
18
+ 'bidcos-binrpc': {
19
+ type: 'boolean',
20
+ describe: 'talk binrpc instead of xmlrpc to BidCos-RF and BidCos-Wired',
21
+ default: false,
22
+ },
23
+ 'listen-address': {
24
+ alias: 'l',
25
+ type: 'string',
26
+ describe: 'address the rpc callback servers bind to (default: first non-loopback ipv4)',
27
+ },
28
+ 'init-address': {
29
+ type: 'string',
30
+ describe: 'address the CCU calls back (default: listen address); needed behind NAT/Docker',
31
+ },
32
+ 'xmlrpc-port': {type: 'number', describe: 'xmlrpc callback server port', default: 2126},
33
+ 'binrpc-port': {type: 'number', describe: 'binrpc callback server port', default: 2127},
34
+ 'ping-timeout': {
35
+ type: 'number',
36
+ describe: 'seconds without an event before ping / re-init (HmIP-RF: 600)',
37
+ default: 60,
38
+ },
39
+ rega: {
40
+ type: 'boolean',
41
+ describe: 'names, rooms, functions, variables and programs from ReGa (--no-rega: addresses only)',
42
+ default: true,
43
+ },
44
+ 'rega-poll-interval': {type: 'number', describe: 'seconds between variable/program polls, 0 = off', default: 30},
45
+ 'rega-names-interval': {
46
+ type: 'number',
47
+ describe:
48
+ 'seconds between re-reads of names, rooms and functions from ReGa, 0 = only at start and on set/rega/sync',
49
+ default: 3600,
50
+ },
51
+ 'rega-poll-trigger': {
52
+ type: 'string',
53
+ describe: 'channel.datapoint whose event triggers a variable/program poll, e.g. BidCoS-RF:50.PRESS_SHORT',
54
+ },
55
+ 'ccu-timezone': {type: 'string', describe: "IANA time zone of the CCU (default: this host's time zone)"},
56
+ 'name-file': {
57
+ alias: 'm',
58
+ type: 'string',
59
+ describe: 'JSON file {address: name} overriding the ReGa names (see example-names.json)',
60
+ file: {
61
+ format: 'json',
62
+ example: 'example-names.json',
63
+ schema: 'names.schema.json',
64
+ describe: 'device and channel names',
65
+ },
66
+ },
67
+ 'item-template': {
68
+ type: 'string',
69
+ describe:
70
+ 'item (topic part after status/ and set/) of a datapoint; ${field} placeholders with | fallbacks, every hm field',
71
+ default: DEFAULT_ITEM_TEMPLATE,
72
+ },
73
+ 'sysvar-item-template': {
74
+ type: 'string',
75
+ describe: 'item of a system variable',
76
+ default: DEFAULT_SYSVAR_ITEM_TEMPLATE,
77
+ },
78
+ 'program-item-template': {type: 'string', describe: 'item of a program', default: DEFAULT_PROGRAM_ITEM_TEMPLATE},
79
+ 'hm-payload': {type: 'boolean', describe: 'add the "hm" meta data block to every status payload', default: true},
80
+ 'plain-tree': {
81
+ type: 'string',
82
+ describe: 'additionally publish plain payloads under <name>/<level>/... (e.g. "state")',
83
+ },
84
+ 'publish-cache': {type: 'boolean', describe: 'publish every datapoint value from ReGa at start', default: false},
85
+ 'publish-counters': {
86
+ type: 'boolean',
87
+ describe: 'publish rpc rx/tx counters on counter/<interface>/rx|tx',
88
+ default: true,
89
+ },
90
+ 'duty-cycle-interval': {type: 'number', describe: 'seconds between duty cycle polls, 0 = off', default: 90},
91
+ 'rpc-topics': {
92
+ type: 'boolean',
93
+ describe: 'accept arbitrary rpc calls on <name>/rpc/<interface>/<method>/<callid> (security surface!)',
94
+ default: false,
95
+ },
96
+ 'state-dir': {
97
+ type: 'string',
98
+ describe:
99
+ 'directory for devices, paramset descriptions, names and last values (default: $STATE_DIRECTORY or ~/.hm2mqtt)',
100
+ default: process.env.STATE_DIRECTORY,
101
+ },
102
+ };
103
+
104
+ export default parseConfig({
105
+ pkg,
106
+ options: OPTIONS,
107
+ defaults: {name: 'hm'},
108
+ examples: [
109
+ ['$0 -a homematic-ccu3 -u mqtt://broker', 'run in the foreground'],
110
+ ['$0 -a 192.168.1.50 -i BidCos-RF,HmIP-RF --plain-tree state', 'two interfaces plus the plain mirror tree'],
111
+ ['sudo $0 --install -n hm -a homematic-ccu3 -u mqtt://broker', 'install as service hm2mqtt@hm'],
112
+ ],
113
+ });
@@ -0,0 +1,6 @@
1
+ {
2
+ "OEQ1234567": "Steckdose Wohnzimmer",
3
+ "OEQ1234567:1": "Steckdose Wohnzimmer",
4
+ "000A1B2C3D4E5F": "Heizung Bad",
5
+ "000A1B2C3D4E5F:1": "Heizung Bad"
6
+ }