homebridge-navilink 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +202 -0
- package/README.md +161 -0
- package/SECURITY.md +73 -0
- package/config.schema.json +138 -0
- package/dist/api/channel.d.ts +94 -0
- package/dist/api/channel.js +334 -0
- package/dist/api/http.d.ts +68 -0
- package/dist/api/http.js +205 -0
- package/dist/api/identity.d.ts +51 -0
- package/dist/api/identity.js +80 -0
- package/dist/api/index.d.ts +17 -0
- package/dist/api/index.js +33 -0
- package/dist/api/mqtt-codec.d.ts +181 -0
- package/dist/api/mqtt-codec.js +377 -0
- package/dist/api/mqtt.d.ts +178 -0
- package/dist/api/mqtt.js +450 -0
- package/dist/api/protocol.d.ts +212 -0
- package/dist/api/protocol.js +286 -0
- package/dist/api/rest.d.ts +139 -0
- package/dist/api/rest.js +317 -0
- package/dist/api/sigv4.d.ts +70 -0
- package/dist/api/sigv4.js +123 -0
- package/dist/api/topics.d.ts +75 -0
- package/dist/api/topics.js +90 -0
- package/dist/devices/base-accessory.d.ts +127 -0
- package/dist/devices/base-accessory.js +232 -0
- package/dist/devices/dhw-accessory.d.ts +62 -0
- package/dist/devices/dhw-accessory.js +100 -0
- package/dist/devices/fault-accessory.d.ts +31 -0
- package/dist/devices/fault-accessory.js +73 -0
- package/dist/devices/heating-accessory.d.ts +63 -0
- package/dist/devices/heating-accessory.js +128 -0
- package/dist/devices/host.d.ts +77 -0
- package/dist/devices/host.js +23 -0
- package/dist/devices/index.d.ts +17 -0
- package/dist/devices/index.js +33 -0
- package/dist/devices/power-accessory.d.ts +32 -0
- package/dist/devices/power-accessory.js +86 -0
- package/dist/devices/probe-accessory.d.ts +45 -0
- package/dist/devices/probe-accessory.js +108 -0
- package/dist/devices/recirculation-accessory.d.ts +47 -0
- package/dist/devices/recirculation-accessory.js +122 -0
- package/dist/devices/thermostat-accessory.d.ts +129 -0
- package/dist/devices/thermostat-accessory.js +372 -0
- package/dist/discovery.d.ts +99 -0
- package/dist/discovery.js +423 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +15 -0
- package/dist/platform.d.ts +120 -0
- package/dist/platform.js +425 -0
- package/dist/session.d.ts +243 -0
- package/dist/session.js +717 -0
- package/dist/settings.d.ts +218 -0
- package/dist/settings.js +240 -0
- package/dist/types/index.d.ts +265 -0
- package/dist/types/index.js +58 -0
- package/dist/ui-api.d.ts +27 -0
- package/dist/ui-api.js +39 -0
- package/dist/utils/context.d.ts +32 -0
- package/dist/utils/context.js +74 -0
- package/dist/utils/errors.d.ts +69 -0
- package/dist/utils/errors.js +118 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.js +31 -0
- package/dist/utils/redact.d.ts +85 -0
- package/dist/utils/redact.js +210 -0
- package/dist/utils/serial.d.ts +18 -0
- package/dist/utils/serial.js +24 -0
- package/dist/utils/temperature.d.ts +114 -0
- package/dist/utils/temperature.js +150 -0
- package/dist/utils/timing.d.ts +68 -0
- package/dist/utils/timing.js +91 -0
- package/dist/utils/validators.d.ts +96 -0
- package/dist/utils/validators.js +353 -0
- package/docs/FEATURES.md +80 -0
- package/docs/PROTOCOL.md +200 -0
- package/docs/README-DETAILED.md +312 -0
- package/homebridge-ui/public/index.html +123 -0
- package/homebridge-ui/public/index.js +503 -0
- package/homebridge-ui/server.js +174 -0
- package/package.json +87 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# homebridge-navilink
|
|
2
|
+
|
|
3
|
+
[](https://github.com/tbaur/homebridge-navilink/actions/workflows/test.yml) [](https://www.npmjs.com/package/homebridge-navilink) [](https://www.npmjs.com/package/homebridge-navilink) [](https://nodejs.org) [](https://homebridge.io) [](LICENSE)
|
|
4
|
+
|
|
5
|
+
**Navien combi boilers and water heaters in Apple HomeKit.** Hot water and space-heating thermostats, recirculation, faults and temperature probes, with changes arriving as they happen rather than on a polling loop. Verified against an NCB-240E (firmware 4352).
|
|
6
|
+
|
|
7
|
+
Scheduling, weekly programmes and commissioning stay in the NaviLink app, which does them properly. This plugin adds the tile, the scene, the automation and the spoken command. It also adds a fault sensor that tells you the boiler has stopped before the shower does.
|
|
8
|
+
|
|
9
|
+
> **This plugin talks to Navien's cloud, not to your boiler.** There is no local API on a NaviLink gateway. It needs your NaviLink account. See [Supported devices](#supported-devices) and [Security](#security) before you install it.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### Per appliance
|
|
14
|
+
|
|
15
|
+
- **Hot water thermostat:** the domestic hot water setpoint, reading the actual outlet temperature. Respects the range your installer set
|
|
16
|
+
- **Heating thermostat:** the space-heating flow temperature. This is the boiler's water temperature, not a room thermostat. Your room thermostat still decides when heat is called for
|
|
17
|
+
- **Power switch:** on and off, with switching *off* refused by default because it stops central heating too
|
|
18
|
+
- **Recirculation switch:** starts the on-demand pump, so hot water reaches the tap without running it first. Only offered where a pump is fitted. The appliance runs the pump for a fixed period and then stops; the tile turns itself off when that happens
|
|
19
|
+
- **Fault sensor:** a contact sensor that opens on an error code, so HomeKit can notify you. The code goes to the log
|
|
20
|
+
- **Temperature sensors:** hot water in and out, heating flow and return, and the outdoor probe if one is fitted. Each disables itself if the appliance does not report it
|
|
21
|
+
|
|
22
|
+
### Reliability
|
|
23
|
+
|
|
24
|
+
- **Push, not polling.** The gateway sends changes as they happen, so a setpoint changed at the wall controller or in the NaviLink app reaches HomeKit in about a second. The poll is only a backstop
|
|
25
|
+
- **A rejected password is never retried.** Repeating a wrong password at a cloud is how an account gets locked. The plugin stops, says so once, and waits for you
|
|
26
|
+
- **Credentials are renewed on a clock,** a few minutes before they expire, so the connection is not already dead in the middle of the night
|
|
27
|
+
- **A connected socket is not a live appliance.** Readings carry the time they were taken, and a stale one becomes No Response instead of yesterday's setpoint
|
|
28
|
+
- **Honest state:** No Response until the appliance has actually been read, never a value it cannot confirm
|
|
29
|
+
- **Never loses your rooms:** a broken config disables the platform without unregistering anything
|
|
30
|
+
|
|
31
|
+
### Quality
|
|
32
|
+
|
|
33
|
+
- **Strict TypeScript,** with `noUncheckedIndexedAccess` and type-aware lint
|
|
34
|
+
- **Tested:** a behavioural Jest suite against fixtures recorded from real hardware, with a guard that fails the build if anything identifying reaches them
|
|
35
|
+
- **No analytics:** nothing is sent anywhere except Navien's own service
|
|
36
|
+
- **One runtime dependency,** Homebridge's own UI helper. The MQTT client is a small in-repo codec, not a `mqtt.js` dependency tree
|
|
37
|
+
|
|
38
|
+
Every accessory, field and log line is documented in [Detailed documentation](docs/README-DETAILED.md).
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### 1. Install
|
|
43
|
+
|
|
44
|
+
**Homebridge UI** (recommended): Plugins → Search `homebridge-navilink` → Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g homebridge-navilink
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Prepare your appliance
|
|
51
|
+
|
|
52
|
+
Your NaviLink gateway must be connected and showing as online in the NaviLink app. Nothing needs enabling: the plugin uses the same service the app does. If the app cannot see the appliance, neither can this.
|
|
53
|
+
|
|
54
|
+
### 3. Configure
|
|
55
|
+
|
|
56
|
+
**Homebridge UI** (recommended): open the plugin settings, enter your NaviLink email and password, and press **Sign in**. Every appliance on the account is listed, along with the accessories it can actually support. A recirculation switch is only offered where a pump is fitted. Tick what you want and press the Homebridge Save button.
|
|
57
|
+
|
|
58
|
+
Or in `config.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"platforms": [
|
|
63
|
+
{
|
|
64
|
+
"platform": "NaviLink",
|
|
65
|
+
"name": "NaviLink",
|
|
66
|
+
"email": "you@example.com",
|
|
67
|
+
"password": "your-navilink-password",
|
|
68
|
+
"devices": [
|
|
69
|
+
{
|
|
70
|
+
"id": "a1b2c3d4e5f6:1",
|
|
71
|
+
"name": "Boiler",
|
|
72
|
+
"dhw": true,
|
|
73
|
+
"heating": true,
|
|
74
|
+
"fault": true
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The `id` is your gateway's MAC address and the channel. The settings page writes it for you; finding it by hand is not worth the effort.
|
|
83
|
+
|
|
84
|
+
See the [full configuration reference](docs/README-DETAILED.md#full-configuration-reference) for every option.
|
|
85
|
+
|
|
86
|
+
### 4. Restart Homebridge
|
|
87
|
+
|
|
88
|
+
Accessories appear in the Home app after restart, showing No Response for the few seconds it takes to sign in and read the first status frame.
|
|
89
|
+
|
|
90
|
+
## Supported Devices
|
|
91
|
+
|
|
92
|
+
Any Navien appliance that the NaviLink app controls. The cloud interface is the same for all of them; what differs is which capabilities an appliance reports.
|
|
93
|
+
|
|
94
|
+
| Verified against | Notes |
|
|
95
|
+
|---|---|
|
|
96
|
+
| **NCB-240E (NG)** | Combi: hot water and space heating, firmware 4352 |
|
|
97
|
+
|
|
98
|
+
Other families are decoded from the same table the NaviLink app uses and are expected to work, but nobody has confirmed them here:
|
|
99
|
+
|
|
100
|
+
| Family | Expected |
|
|
101
|
+
|---|---|
|
|
102
|
+
| **NPE, NPE2, NPN** | Tankless water heaters. Hot water only; the heating thermostat disables itself |
|
|
103
|
+
| **NCB-H** | Combi with a buffer tank |
|
|
104
|
+
| **NHB** | Boiler. Space heating only |
|
|
105
|
+
| **NFB, NFC** | Boilers with hot water and space heating |
|
|
106
|
+
| **NVW** | Water heater with a tank |
|
|
107
|
+
|
|
108
|
+
If yours is not listed, it will most likely work. Please open an issue with the output of `node scripts/capture-fixture.js --redact` either way, so the table can say so with confidence.
|
|
109
|
+
|
|
110
|
+
## Configuration Options
|
|
111
|
+
|
|
112
|
+
Only one `NaviLink` platform block is supported. It can hold as many appliances as the account owns.
|
|
113
|
+
|
|
114
|
+
| Option | Required to run | Description |
|
|
115
|
+
|---|:-:|---|
|
|
116
|
+
| `name` | ✓ | Plugin instance name shown in Homebridge logs |
|
|
117
|
+
| `email` | ✓ | Your NaviLink account address. Needed before the plugin signs in |
|
|
118
|
+
| `password` | ✓ | Your NaviLink password. Needed before the plugin signs in |
|
|
119
|
+
| `devices` | ✓ | List of appliances. Needed before the plugin signs in |
|
|
120
|
+
| `options.statusIntervalSec` | | Backstop refresh, 30–3600 seconds (default 120) |
|
|
121
|
+
| `options.readOnly` | | Report everything, change nothing (default false) |
|
|
122
|
+
| `options.allowPowerOff` | | Let HomeKit switch the appliance off (default false) |
|
|
123
|
+
|
|
124
|
+
Each entry in `devices[]` takes `id` and `name`, plus an optional `channel` and one flag per accessory: `dhw`, `heating`, `power`, `recirculation`, `fault`, `temperatureSensors` and `outdoorSensor`. The [detailed documentation](docs/README-DETAILED.md#devices-entries) describes each one.
|
|
125
|
+
|
|
126
|
+
## Not Working?
|
|
127
|
+
|
|
128
|
+
1. **"NaviLink rejected the email address or password."** Sign in to the NaviLink app with the same credentials. The plugin has stopped trying on purpose, so fix the password and restart Homebridge
|
|
129
|
+
2. **Everything shows No Response.** Check the log for `the NaviLink platform is disabled`, which means the configuration could not be read
|
|
130
|
+
3. **The heating thermostat says it has no loop.** Your appliance reports no space-heating circuit. Turn the accessory off in the settings
|
|
131
|
+
4. **A recirculation switch that is not offered.** No pump is fitted, or it is not commissioned. Check the NaviLink app
|
|
132
|
+
5. **"The appliance refused a command for arriving too soon."** The cloud rate-limits control. The plugin pauses and retries on your next press
|
|
133
|
+
|
|
134
|
+
The [full troubleshooting list](docs/README-DETAILED.md#troubleshooting) covers more, including what Off on the hot water tile does once you allow power-off.
|
|
135
|
+
|
|
136
|
+
## Security
|
|
137
|
+
|
|
138
|
+
This plugin needs your NaviLink password, stores it in the Homebridge configuration file as every Homebridge credential is stored, and sends it to Navien to sign in. It is never written to the Homebridge log, never put into an accessory's cache, and redacted from anything the plugin prints. That is the honest summary; [SECURITY.md](SECURITY.md) has the detail, including what a capture contains and why the fixtures in this repository are pseudonymised.
|
|
139
|
+
|
|
140
|
+
## Requirements
|
|
141
|
+
|
|
142
|
+
- Homebridge 2.x
|
|
143
|
+
- Node.js 22, 24 or 26, matching what Homebridge 2.x itself supports
|
|
144
|
+
- A North American NaviLink account (`nlus`). Other Navien regions use different hosts and will look like a rejected password
|
|
145
|
+
- A NaviLink account with at least one gateway online
|
|
146
|
+
- A working internet connection
|
|
147
|
+
|
|
148
|
+
## More Info
|
|
149
|
+
|
|
150
|
+
- [Detailed documentation](docs/README-DETAILED.md)
|
|
151
|
+
- [Features](docs/FEATURES.md)
|
|
152
|
+
- [Protocol reference](docs/PROTOCOL.md): what the NaviLink cloud actually does
|
|
153
|
+
- [Development](DEVELOPMENT.md)
|
|
154
|
+
- [Report Issues](https://github.com/tbaur/homebridge-navilink/issues)
|
|
155
|
+
- [Changelog](CHANGELOG.md)
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
Copyright 2026 tbaur
|
|
160
|
+
|
|
161
|
+
Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) file for details.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | ------------------ |
|
|
7
|
+
| 0.x.x | ✅ Active support |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
Do not open a public issue. Use GitHub's [private vulnerability reporting](https://github.com/tbaur/homebridge-navilink/security/advisories/new), and include a description, how to reproduce it, and the impact.
|
|
12
|
+
|
|
13
|
+
## The honest summary
|
|
14
|
+
|
|
15
|
+
**This plugin needs your NaviLink password and stores it in plain text in the Homebridge configuration file.** That is how every Homebridge plugin that talks to a cloud service works, because Homebridge offers no secret store. It deserves saying plainly.
|
|
16
|
+
|
|
17
|
+
What follows from that:
|
|
18
|
+
|
|
19
|
+
- Anyone who can read your Homebridge config can sign in to your NaviLink account, which controls your boiler.
|
|
20
|
+
- The plugin uses an interface Navien has never published. Navien can change or withdraw it at any time, without notice, and would be within their rights to.
|
|
21
|
+
- There is no local fallback. A NaviLink gateway has no LAN interface, so this stops working when your internet does.
|
|
22
|
+
|
|
23
|
+
If those are not acceptable, this plugin is not for you, and that is a reasonable conclusion.
|
|
24
|
+
|
|
25
|
+
## Security Measures
|
|
26
|
+
|
|
27
|
+
- **Credentials in one place.** The password is read from configuration, used to sign in, and held only in memory. It is never written to a log, never placed in an accessory's cache, never sent anywhere except Navien's sign-in endpoint over HTTPS, and never passed to a script as a command-line argument.
|
|
28
|
+
- **Redaction by shape, not by name.** `src/utils/redact.ts` matches JWTs, AWS key ids, signed-URL parameters and credential-shaped JSON fields by their *form*. A field name list would miss a token in a response shape nobody anticipated; this does not.
|
|
29
|
+
- **Masked identifiers in the log.** The account address appears as `s…e@example.com` and a gateway MAC as `…E5F6`. Both identify you, and a Homebridge log gets pasted into issues.
|
|
30
|
+
- **The accessory cache holds identity, not credentials.** Homebridge persists `{mac}:{channel}` as `deviceId` so a restart adopts the same tile. That file is plain JSON and is included in diagnostic bundles, so it must never hold the password, a token or a signed AWS URL. The MAC is the appliance's address in every MQTT topic. HomeKit serial numbers are opaque generated values, not the MAC.
|
|
31
|
+
- **HomeKit serial numbers are opaque generated values,** not the gateway MAC. The Home app displays them, so they reach screenshots.
|
|
32
|
+
- **Input validation.** Config is checked at startup. A missing account, or a `devices` value that is not a list, disables the platform without unregistering accessories. A bad appliance entry is skipped. Names are stripped of control characters and length-capped before they reach a log line or a characteristic.
|
|
33
|
+
- **Bounded I/O.** Separate connect and total timeouts on every request, a capped HTTP response size, and a capped MQTT packet size, so a hostile or broken response cannot exhaust memory.
|
|
34
|
+
- **A rejected credential stops the session.** Retrying a wrong password is how an account gets locked; the plugin declines to do it.
|
|
35
|
+
- **Minimal dependencies.** One at runtime: Homebridge's own UI helper. The MQTT client is in this repository, for a protocol reason ([PROTOCOL.md](docs/PROTOCOL.md)) that also reduces supply-chain surface.
|
|
36
|
+
- **Dependencies audited.** CI runs `npm audit` on the runtime tree and OSV-Scanner on the full tree.
|
|
37
|
+
- **A CI step rejects credential-shaped strings** in the published docs, fixtures, schema and issue templates, so a token cannot be committed by accident. Unit tests that hold fake JWTs are outside that scan on purpose.
|
|
38
|
+
|
|
39
|
+
## The settings page
|
|
40
|
+
|
|
41
|
+
The configuration UI runs in its own short-lived process and is the one place that handles a typed password.
|
|
42
|
+
|
|
43
|
+
- The password is used for the sign-in of the request that carried it. It is not cached between requests and not written to a file by that process.
|
|
44
|
+
- Nothing from a sign-in response reaches the browser. The page receives appliances; the tokens and AWS credentials stay in the UI process and die with the request.
|
|
45
|
+
- Diagnostic output handed back on failure is the plugin's own redacted log, filtered a second time on the way out, because a line that reaches a browser can end up in a screenshot in a public issue.
|
|
46
|
+
|
|
47
|
+
## Captures and fixtures
|
|
48
|
+
|
|
49
|
+
A raw frame from the NaviLink cloud carries your gateway's MAC address and your account's sequence numbers. The `device/info` endpoint also returns your installation's **street address and coordinates**, which is why the plugin reads only the firmware version from it and nothing else is available to callers.
|
|
50
|
+
|
|
51
|
+
- Raw captures go to `tests/fixtures/raw/`, which is git-ignored.
|
|
52
|
+
- `scripts/pseudonymise.js` rewrites them and then audits its own output. It reports every identifier that remains. It does not trust a list of field names. A MAC appears twice in two spellings in these frames, and a name-driven rewrite misses the second.
|
|
53
|
+
- `tests/unit/fixtures.test.ts` fails the build if a MAC, email address, JWT or AWS key that is not the documented example appears in `tests/fixtures/`.
|
|
54
|
+
- `scripts/capture-fixture.js --redact` is the form to paste into a bug report. Read it before you paste it: the redaction is good, and it is not a promise.
|
|
55
|
+
|
|
56
|
+
## Best Practices for Users
|
|
57
|
+
|
|
58
|
+
1. Keep Homebridge and this plugin updated.
|
|
59
|
+
2. Run Homebridge with minimal privileges, and do not expose it to the internet.
|
|
60
|
+
3. Protect the Homebridge configuration file and any backup of it as you would a password file, because it contains one.
|
|
61
|
+
4. Use `options.readOnly` if you want the readings without the plugin being able to change anything.
|
|
62
|
+
5. Leave `options.allowPowerOff` off unless you have thought about what "turn everything off" means in February.
|
|
63
|
+
6. Consider a NaviLink account used only for this, if you would rather not have your primary one in a config file.
|
|
64
|
+
|
|
65
|
+
## Response Timeline
|
|
66
|
+
|
|
67
|
+
- **Acknowledgment**: Within 48 hours
|
|
68
|
+
- **Initial assessment**: Within 1 week
|
|
69
|
+
- **Fix timeline**: Depends on severity
|
|
70
|
+
- Critical: 24-48 hours
|
|
71
|
+
- High: 1 week
|
|
72
|
+
- Medium: 2 weeks
|
|
73
|
+
- Low: Next release
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "NaviLink",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"singular": true,
|
|
5
|
+
"customUi": true,
|
|
6
|
+
"customUiPath": "./homebridge-ui",
|
|
7
|
+
"headerDisplay": "Exposes Navien combi boilers and water heaters to HomeKit through the North American NaviLink cloud (`nlus`): hot water and space-heating thermostats, a power switch, recirculation, a fault sensor and temperature probes. Verified on an NCB-240E. Press **Sign in** to list the appliances on your account; every field below can also be edited by hand.",
|
|
8
|
+
"footerDisplay": "Your NaviLink password is stored in the Homebridge configuration file, because the plugin has to sign in again after a restart and Navien offers no other credential. See the [documentation](https://github.com/tbaur/homebridge-navilink#readme) for what this plugin does and does not do.",
|
|
9
|
+
"schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["name"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"name": {
|
|
14
|
+
"title": "Platform Name",
|
|
15
|
+
"type": "string",
|
|
16
|
+
"default": "NaviLink",
|
|
17
|
+
"description": "Shown in the Homebridge log."
|
|
18
|
+
},
|
|
19
|
+
"email": {
|
|
20
|
+
"title": "NaviLink Email",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"format": "email",
|
|
23
|
+
"maxLength": 254,
|
|
24
|
+
"description": "The email address for your NaviLink account, the same one you use in the NaviLink app."
|
|
25
|
+
},
|
|
26
|
+
"password": {
|
|
27
|
+
"title": "NaviLink Password",
|
|
28
|
+
"type": "string",
|
|
29
|
+
"maxLength": 256,
|
|
30
|
+
"x-schema-form": { "type": "password" },
|
|
31
|
+
"description": "Stored in plain text in the Homebridge configuration file, as every Homebridge credential is. It is never written to the Homebridge log."
|
|
32
|
+
},
|
|
33
|
+
"options": {
|
|
34
|
+
"title": "Options",
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"statusIntervalSec": {
|
|
38
|
+
"title": "Status Refresh (seconds)",
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"default": 120,
|
|
41
|
+
"minimum": 30,
|
|
42
|
+
"maximum": 3600,
|
|
43
|
+
"description": "A floor on how stale a reading can be. The appliance pushes changes as they happen, so this is not how state normally arrives; it is the backstop for a push that was missed."
|
|
44
|
+
},
|
|
45
|
+
"readOnly": {
|
|
46
|
+
"title": "Read-only",
|
|
47
|
+
"type": "boolean",
|
|
48
|
+
"default": false,
|
|
49
|
+
"description": "Report everything, change nothing. Every accessory still shows state, and a HomeKit write is declined with one explanatory line in the log."
|
|
50
|
+
},
|
|
51
|
+
"allowPowerOff": {
|
|
52
|
+
"title": "Allow HomeKit to Switch the Appliance Off",
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"default": false,
|
|
55
|
+
"description": "Off by default, and worth leaving off. On a combi appliance the power state governs central heating as well as hot water, so \"turn off the water heater\" said to Siri, or a scene that turns everything off, would stop the heating in a house that may be empty and freezing. With this off, a power-off request is declined and explained instead of obeyed."
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"devices": {
|
|
60
|
+
"title": "Appliances",
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"title": "Appliance",
|
|
65
|
+
"required": ["id", "name"],
|
|
66
|
+
"properties": {
|
|
67
|
+
"id": {
|
|
68
|
+
"title": "Identity",
|
|
69
|
+
"type": "string",
|
|
70
|
+
"minLength": 3,
|
|
71
|
+
"maxLength": 20,
|
|
72
|
+
"pattern": "^[0-9a-fA-F]{12}:([1-9]|[12][0-9]|3[0-2])$",
|
|
73
|
+
"examples": ["a1b2c3d4e5f6:1"],
|
|
74
|
+
"description": "Stable identity: twelve hex digits and the channel, as the settings page writes it (lowercase, no separators). Changing it detaches the accessories from their HomeKit rooms and automations."
|
|
75
|
+
},
|
|
76
|
+
"name": {
|
|
77
|
+
"title": "Name",
|
|
78
|
+
"type": "string",
|
|
79
|
+
"maxLength": 64,
|
|
80
|
+
"examples": ["Zone One"],
|
|
81
|
+
"description": "The appliance's name. Accessories are named from it: \"Boiler\" gives \"Boiler Hot Water\", \"Boiler Heating\", \"Boiler Fault\" and so on."
|
|
82
|
+
},
|
|
83
|
+
"channel": {
|
|
84
|
+
"title": "Channel",
|
|
85
|
+
"type": "integer",
|
|
86
|
+
"default": 1,
|
|
87
|
+
"minimum": 1,
|
|
88
|
+
"maximum": 32,
|
|
89
|
+
"description": "1 for a single appliance. A cascade of several appliances behind one gateway uses a channel each."
|
|
90
|
+
},
|
|
91
|
+
"dhw": {
|
|
92
|
+
"title": "Hot Water Thermostat",
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"default": true,
|
|
95
|
+
"description": "The domestic hot water setpoint, as a HomeKit thermostat. Reads the outlet temperature. Switching it off does not switch the appliance off unless you also allow that above."
|
|
96
|
+
},
|
|
97
|
+
"heating": {
|
|
98
|
+
"title": "Heating Thermostat",
|
|
99
|
+
"type": "boolean",
|
|
100
|
+
"default": false,
|
|
101
|
+
"description": "The space-heating water setpoint, as a HomeKit thermostat. This is the boiler's flow temperature, not a room thermostat: it sets how hot the water going to your radiators is, and your existing room thermostat still decides when heat is called for. Only useful on a combi; an appliance with no heating loop disables it and says so in the log."
|
|
102
|
+
},
|
|
103
|
+
"power": {
|
|
104
|
+
"title": "Power Switch",
|
|
105
|
+
"type": "boolean",
|
|
106
|
+
"default": false,
|
|
107
|
+
"description": "A switch for the appliance's power state. Switching it off is refused unless \"Allow HomeKit to switch the appliance off\" is on."
|
|
108
|
+
},
|
|
109
|
+
"recirculation": {
|
|
110
|
+
"title": "Recirculation Switch",
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"default": false,
|
|
113
|
+
"description": "Starts the on-demand hot water recirculation pump, so hot water reaches the tap without running it first. The appliance runs the pump for a fixed period and then stops; the switch turns itself off when that happens. Only for appliances with a pump fitted and commissioned."
|
|
114
|
+
},
|
|
115
|
+
"fault": {
|
|
116
|
+
"title": "Fault Sensor",
|
|
117
|
+
"type": "boolean",
|
|
118
|
+
"default": false,
|
|
119
|
+
"description": "A contact sensor that opens when the appliance reports an error code, so HomeKit can notify you. The code itself is written to the log."
|
|
120
|
+
},
|
|
121
|
+
"temperatureSensors": {
|
|
122
|
+
"title": "Temperature Sensors",
|
|
123
|
+
"type": "boolean",
|
|
124
|
+
"default": false,
|
|
125
|
+
"description": "Four read-only sensors: hot water in and out, and heating flow and return. Each one disables itself if the appliance turns out not to report it."
|
|
126
|
+
},
|
|
127
|
+
"outdoorSensor": {
|
|
128
|
+
"title": "Outdoor Temperature",
|
|
129
|
+
"type": "boolean",
|
|
130
|
+
"default": false,
|
|
131
|
+
"description": "The outdoor probe, on an installation that has one fitted for weather compensation. Most do not."
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|