homebridge-nuheat2 1.2.11 → 1.2.13
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 +25 -0
- package/README.md +22 -8
- package/config.schema.json +127 -50
- package/homebridge-ui/public/index.html +244 -0
- package/homebridge-ui/public/index.js +689 -0
- package/homebridge-ui/public/styles.css +371 -0
- package/index.js +5 -3
- package/lib/NuHeatAPI.js +2 -1
- package/lib/NuHeatListener.js +47 -8
- package/lib/NuHeatThermostat.js +66 -25
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@ All notable changes to this project should be documented in this file
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.2.13] - 2026-04-24
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Subscribe to Nuheat schedule notifications alongside thermostat and group notifications
|
|
12
|
+
- Remove an unused Homebridge UI utility dependency from the published package
|
|
13
|
+
- Improve Homebridge Config UI labels, defaults, grouping, and sensitive-field handling
|
|
14
|
+
- Add a custom Homebridge admin UI aligned with the shared Roborock design system
|
|
15
|
+
- Document the upcoming PKCE public-client direction for Nuheat OAuth credentials
|
|
16
|
+
- Enforce a 30-second minimum polling interval at runtime to reduce accidental API load
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Correct refresh-token rotation debug logging so it compares against the previous token
|
|
21
|
+
- Keep notification de-duplication bookkeeping consistent across mixed notification batches
|
|
22
|
+
|
|
23
|
+
## [1.2.12] - 2026-04-21
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Treat Nuheat thermostats as heat-only in HomeKit so the target mode no longer advertises a misleading off option
|
|
28
|
+
- Translate any incoming HomeKit off request into the minimum Nuheat setpoint instead of bouncing back after refresh
|
|
29
|
+
- Apply the Nuheat account temperature scale to the thermostat display-units characteristic so HomeKit shows the correct hardware display unit
|
|
30
|
+
- Coalesce and briefly de-duplicate repeated SignalR thermostat and group notifications to reduce redundant full refreshes and log noise
|
|
31
|
+
|
|
7
32
|
## [1.2.11] - 2026-04-21
|
|
8
33
|
|
|
9
34
|
### Fixed
|
package/README.md
CHANGED
|
@@ -44,7 +44,13 @@ The published package name for this maintained fork is `homebridge-nuheat2`. The
|
|
|
44
44
|
|
|
45
45
|
## Configuration
|
|
46
46
|
|
|
47
|
-
Most users should configure the plugin through Homebridge
|
|
47
|
+
Most users should configure the plugin through the custom Homebridge admin UI. It is organized into Account, Accessories, Behavior, Advanced OAuth, and Diagnostics panels and writes the same config keys shown below.
|
|
48
|
+
|
|
49
|
+
Sensitive values are handled deliberately: saved passwords and legacy client secrets are not redisplayed in the UI. Leave those fields blank to keep the saved value, enter a new value to replace it, or use the Clear Overrides button in Advanced OAuth to remove OAuth overrides.
|
|
50
|
+
|
|
51
|
+
The Diagnostics panel summarizes the saved configuration and exposure strategy before restart. It does not make live Nuheat API calls.
|
|
52
|
+
|
|
53
|
+
The equivalent JSON looks like this:
|
|
48
54
|
|
|
49
55
|
```json
|
|
50
56
|
{
|
|
@@ -52,9 +58,14 @@ Most users should configure the plugin through Homebridge Config UI X, but the e
|
|
|
52
58
|
"name": "NuHeat",
|
|
53
59
|
"email": "email@address.com",
|
|
54
60
|
"password": "password123",
|
|
55
|
-
"devices": [
|
|
61
|
+
"devices": [
|
|
62
|
+
{ "serialNumber": "1111111", "disabled": false },
|
|
63
|
+
{ "serialNumber": "2222222", "disabled": false }
|
|
64
|
+
],
|
|
56
65
|
"autoPopulateAwayModeSwitches": true,
|
|
66
|
+
"groups": [{ "groupName": "Main Floor", "disabled": false }],
|
|
57
67
|
"exposeScheduleSwitches": false,
|
|
68
|
+
"enableNotifications": true,
|
|
58
69
|
"holdLength": 1440,
|
|
59
70
|
"refresh": 60
|
|
60
71
|
}
|
|
@@ -69,15 +80,17 @@ Most users should configure the plugin through Homebridge Config UI X, but the e
|
|
|
69
80
|
- `password`: MyNuheat account password
|
|
70
81
|
- `devices`: Optional list of thermostats to expose. If omitted or empty, every thermostat on the account will be discovered automatically. Blank rows in the UI are ignored
|
|
71
82
|
- `serialNumber`: Thermostat serial number from MyNuheat
|
|
83
|
+
- `disabled`: Available on `devices` and `groups` rows. Keeps the row saved while preventing that thermostat or group from being exposed
|
|
72
84
|
- `autoPopulateAwayModeSwitches`: Automatically expose away-mode switches for all groups on the account
|
|
73
85
|
- `exposeScheduleSwitches`: Optionally expose a switch per thermostat that reflects whether the thermostat is following its schedule and can be turned on to resume the schedule
|
|
74
86
|
- `groups`: Optional allow-list of groups to expose as away-mode switches. This only affects group/away-mode accessories. Blank rows in the UI are ignored
|
|
75
87
|
- `groupName`: Group name as shown in MyNuheat
|
|
76
|
-
- `holdLength`: Hold duration in minutes
|
|
77
|
-
- `refresh`: Poll interval in seconds, default `60`
|
|
78
|
-
- `
|
|
79
|
-
- `
|
|
80
|
-
- `
|
|
88
|
+
- `holdLength`: Hold duration in minutes, default `1440`. Values are clamped from `0` to `1440`
|
|
89
|
+
- `refresh`: Poll interval in seconds, default `60`. Values lower than `30` are raised to `30` to reduce API traffic
|
|
90
|
+
- `enableNotifications`: Enables Nuheat SignalR notifications for faster updates. Defaults to `true`; set to `false` only while troubleshooting
|
|
91
|
+
- `debug`: Enables verbose Nuheat API, notification, and accessory logging. Defaults to `false`
|
|
92
|
+
- `clientId`: Optional advanced override for the Nuheat OAuth client ID. Current releases require this to be paired with `clientSecret`; PKCE public-client support is planned but is not active yet
|
|
93
|
+
- `clientSecret`: Optional legacy OAuth client secret override for confidential-client credentials. Required with a custom `clientId` until PKCE support ships. Do not publish or share this value
|
|
81
94
|
- `redirectUri`: Optional advanced override for the Nuheat OAuth redirect URI, default `http://localhost`
|
|
82
95
|
|
|
83
96
|
### Hold Length Behavior
|
|
@@ -101,7 +114,7 @@ Nuheat's public OpenAPI documentation indicates that third-party developers shou
|
|
|
101
114
|
- [Nuheat OpenAPI docs](https://api.mynuheat.com/)
|
|
102
115
|
- [Nuheat API access request page](https://www.nuheat.com/openapi)
|
|
103
116
|
|
|
104
|
-
This fork still supports the legacy built-in OAuth client settings as a fallback
|
|
117
|
+
This fork still supports the legacy built-in OAuth client settings as a fallback. Nuheat is expected to issue a PKCE-based public client for this integration so the plugin can eventually ship with a public `clientId` without distributing a client secret. Until that migration is complete, keep any issued `clientSecret` out of GitHub, npm, screenshots, and shared logs.
|
|
105
118
|
|
|
106
119
|
## What's New In This Fork
|
|
107
120
|
|
|
@@ -161,5 +174,6 @@ After that, bump the version in `package.json`, push to `master`, and GitHub Act
|
|
|
161
174
|
## Future Work
|
|
162
175
|
|
|
163
176
|
- Validate the plugin against the official Nuheat API credentials requested for this integration.
|
|
177
|
+
- Move the normal OAuth path to Nuheat's PKCE-based public client once the new client details are issued.
|
|
164
178
|
- Verify group and away-mode behavior against current live API responses.
|
|
165
179
|
- Evaluate whether SignalR notifications can reduce polling further in real-world deployments.
|
package/config.schema.json
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
"pluginAlias": "NuHeat",
|
|
3
3
|
"pluginType": "platform",
|
|
4
4
|
"singular": false,
|
|
5
|
+
"customUi": true,
|
|
6
|
+
"customUiPath": "./homebridge-ui",
|
|
7
|
+
"headerDisplay": "Connect Nuheat Signature floor-heating thermostats to HomeKit. Most users only need their MyNuheat account email and password.",
|
|
8
|
+
"footerDisplay": "The npm package is homebridge-nuheat2, but the Homebridge platform remains NuHeat for backward compatibility.",
|
|
5
9
|
"schema": {
|
|
6
10
|
"type": "object",
|
|
7
11
|
"required": [
|
|
@@ -10,104 +14,177 @@
|
|
|
10
14
|
"password"
|
|
11
15
|
],
|
|
12
16
|
"properties": {
|
|
17
|
+
"platform": {
|
|
18
|
+
"title": "Platform",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"default": "NuHeat",
|
|
21
|
+
"const": "NuHeat",
|
|
22
|
+
"description": "Homebridge platform identifier. Keep this set to NuHeat."
|
|
23
|
+
},
|
|
13
24
|
"name": {
|
|
14
|
-
"title": "Name",
|
|
25
|
+
"title": "Platform Name",
|
|
15
26
|
"type": "string",
|
|
16
|
-
"default": "NuHeat"
|
|
27
|
+
"default": "NuHeat",
|
|
28
|
+
"description": "Display name used for this platform instance in Homebridge logs."
|
|
17
29
|
},
|
|
18
30
|
"email": {
|
|
19
|
-
"title": "
|
|
31
|
+
"title": "MyNuheat Email",
|
|
20
32
|
"type": "string",
|
|
21
|
-
"format": "email"
|
|
33
|
+
"format": "email",
|
|
34
|
+
"description": "Email address for the MyNuheat account that owns the thermostats."
|
|
22
35
|
},
|
|
23
36
|
"password": {
|
|
24
|
-
"title": "
|
|
25
|
-
"type": "string"
|
|
26
|
-
},
|
|
27
|
-
"clientId": {
|
|
28
|
-
"title": "Nuheat Client ID",
|
|
29
|
-
"type": "string",
|
|
30
|
-
"description": "Optional advanced override. Leave blank to use the built-in default client ID."
|
|
31
|
-
},
|
|
32
|
-
"clientSecret": {
|
|
33
|
-
"title": "Nuheat Client Secret",
|
|
34
|
-
"type": "string",
|
|
35
|
-
"description": "Optional advanced override. Leave blank to use the built-in default client secret."
|
|
36
|
-
},
|
|
37
|
-
"redirectUri": {
|
|
38
|
-
"title": "Nuheat Redirect URI",
|
|
37
|
+
"title": "MyNuheat Password",
|
|
39
38
|
"type": "string",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
39
|
+
"format": "password",
|
|
40
|
+
"description": "Password for the MyNuheat account."
|
|
42
41
|
},
|
|
43
42
|
"devices": {
|
|
44
|
-
"title": "
|
|
43
|
+
"title": "Thermostat Allow-List",
|
|
45
44
|
"type": "array",
|
|
46
|
-
"
|
|
45
|
+
"default": [],
|
|
46
|
+
"description": "Optional. Leave empty to expose every thermostat on the account. Add rows only if you want to limit HomeKit to specific thermostat serial numbers.",
|
|
47
47
|
"items": {
|
|
48
48
|
"type": "object",
|
|
49
49
|
"properties": {
|
|
50
50
|
"serialNumber": {
|
|
51
51
|
"title": "Serial Number",
|
|
52
|
-
"type": "string"
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "Thermostat serial number from MyNuheat."
|
|
53
54
|
},
|
|
54
55
|
"disabled": {
|
|
55
56
|
"title": "Disabled",
|
|
56
|
-
"type": "boolean"
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"default": false,
|
|
59
|
+
"description": "Keep this row in the config but do not expose this thermostat."
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
},
|
|
61
|
-
"autoPopulateAwayModeSwitches": {
|
|
62
|
-
"title": "Auto populate Away Mode switches for all available groups",
|
|
63
|
-
"type": "boolean"
|
|
64
|
-
},
|
|
65
|
-
"exposeScheduleSwitches": {
|
|
66
|
-
"title": "Expose per-thermostat schedule switches",
|
|
67
|
-
"type": "boolean",
|
|
68
|
-
"description": "Creates a switch for each thermostat that reflects whether its schedule is active and can be turned on to resume the configured schedule."
|
|
69
|
-
},
|
|
70
64
|
"groups": {
|
|
71
|
-
"title": "
|
|
65
|
+
"title": "Away Mode Group Allow-List",
|
|
72
66
|
"type": "array",
|
|
73
|
-
"
|
|
67
|
+
"default": [],
|
|
68
|
+
"description": "Optional. Leave empty unless you want specific Nuheat groups exposed as away-mode switches.",
|
|
74
69
|
"items": {
|
|
75
70
|
"type": "object",
|
|
76
71
|
"properties": {
|
|
77
72
|
"groupName": {
|
|
78
73
|
"title": "Group Name",
|
|
79
|
-
"type": "string"
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "Group name exactly as shown in MyNuheat."
|
|
80
76
|
},
|
|
81
77
|
"disabled": {
|
|
82
78
|
"title": "Disabled",
|
|
83
|
-
"type": "boolean"
|
|
79
|
+
"type": "boolean",
|
|
80
|
+
"default": false,
|
|
81
|
+
"description": "Keep this row in the config but do not expose this group."
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
},
|
|
86
|
+
"autoPopulateAwayModeSwitches": {
|
|
87
|
+
"title": "Expose Away Mode Switches For All Groups",
|
|
88
|
+
"type": "boolean",
|
|
89
|
+
"default": false,
|
|
90
|
+
"description": "Automatically create HomeKit away-mode switches for every Nuheat group on the account."
|
|
91
|
+
},
|
|
92
|
+
"exposeScheduleSwitches": {
|
|
93
|
+
"title": "Expose Schedule Switches",
|
|
94
|
+
"type": "boolean",
|
|
95
|
+
"default": false,
|
|
96
|
+
"description": "Create one switch per thermostat. The switch is on when the thermostat follows its Nuheat schedule and can be turned on to resume the schedule."
|
|
97
|
+
},
|
|
88
98
|
"holdLength": {
|
|
89
|
-
"title": "Hold Length (
|
|
99
|
+
"title": "Hold Length (minutes)",
|
|
90
100
|
"type": "integer",
|
|
91
|
-
"
|
|
92
|
-
"
|
|
101
|
+
"default": 1440,
|
|
102
|
+
"minimum": 0,
|
|
103
|
+
"maximum": 1440,
|
|
104
|
+
"description": "Duration for HomeKit setpoint changes. Use 0 to hold until the next scheduled event, 1-1439 for a timed hold, or 1440 for a permanent hold."
|
|
93
105
|
},
|
|
94
106
|
"refresh": {
|
|
95
|
-
"title": "
|
|
107
|
+
"title": "Polling Interval (seconds)",
|
|
96
108
|
"type": "integer",
|
|
97
|
-
"
|
|
98
|
-
"minimum":
|
|
99
|
-
|
|
100
|
-
"debug": {
|
|
101
|
-
"title": "Enable debug logs",
|
|
102
|
-
"type": "boolean"
|
|
109
|
+
"default": 60,
|
|
110
|
+
"minimum": 30,
|
|
111
|
+
"description": "How often to poll Nuheat as a safety net. Notifications update faster when enabled; avoid very low values to reduce API traffic."
|
|
103
112
|
},
|
|
104
113
|
"enableNotifications": {
|
|
105
|
-
"title": "Enable Nuheat
|
|
114
|
+
"title": "Enable Nuheat Notifications",
|
|
106
115
|
"type": "boolean",
|
|
107
|
-
"
|
|
116
|
+
"default": true,
|
|
117
|
+
"description": "Use Nuheat SignalR notifications for faster updates. Disable only while troubleshooting, which leaves polling as the fallback."
|
|
118
|
+
},
|
|
119
|
+
"debug": {
|
|
120
|
+
"title": "Enable Debug Logs",
|
|
121
|
+
"type": "boolean",
|
|
122
|
+
"default": false,
|
|
123
|
+
"description": "Write detailed Nuheat API and accessory activity to the Homebridge log."
|
|
124
|
+
},
|
|
125
|
+
"clientId": {
|
|
126
|
+
"title": "Nuheat Client ID",
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Advanced OAuth override. Current releases require this to be paired with a clientSecret; PKCE public-client support is planned but not active yet."
|
|
129
|
+
},
|
|
130
|
+
"clientSecret": {
|
|
131
|
+
"title": "Nuheat Client Secret (Legacy)",
|
|
132
|
+
"type": "string",
|
|
133
|
+
"format": "password",
|
|
134
|
+
"description": "Advanced OAuth override for confidential-client credentials. Required with a custom clientId until PKCE support ships. Do not publish or share this value."
|
|
135
|
+
},
|
|
136
|
+
"redirectUri": {
|
|
137
|
+
"title": "Nuheat Redirect URI",
|
|
138
|
+
"type": "string",
|
|
139
|
+
"default": "http://localhost",
|
|
140
|
+
"description": "Advanced OAuth redirect URI. The default is http://localhost."
|
|
108
141
|
}
|
|
109
142
|
}
|
|
110
143
|
},
|
|
144
|
+
"layout": [
|
|
145
|
+
"platform",
|
|
146
|
+
"name",
|
|
147
|
+
"email",
|
|
148
|
+
"password",
|
|
149
|
+
{
|
|
150
|
+
"type": "fieldset",
|
|
151
|
+
"title": "Accessories",
|
|
152
|
+
"expandable": true,
|
|
153
|
+
"expanded": false,
|
|
154
|
+
"description": "Control which Nuheat thermostats and group switches appear in HomeKit.",
|
|
155
|
+
"items": [
|
|
156
|
+
"devices",
|
|
157
|
+
"autoPopulateAwayModeSwitches",
|
|
158
|
+
"groups",
|
|
159
|
+
"exposeScheduleSwitches"
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"type": "fieldset",
|
|
164
|
+
"title": "Behavior",
|
|
165
|
+
"expandable": true,
|
|
166
|
+
"expanded": false,
|
|
167
|
+
"description": "Tune holds, refresh behavior, notifications, and logging.",
|
|
168
|
+
"items": [
|
|
169
|
+
"holdLength",
|
|
170
|
+
"refresh",
|
|
171
|
+
"enableNotifications",
|
|
172
|
+
"debug"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"type": "fieldset",
|
|
177
|
+
"title": "Advanced OAuth",
|
|
178
|
+
"expandable": true,
|
|
179
|
+
"expanded": false,
|
|
180
|
+
"description": "Only change these fields when testing Nuheat-issued API credentials.",
|
|
181
|
+
"items": [
|
|
182
|
+
"clientId",
|
|
183
|
+
"clientSecret",
|
|
184
|
+
"redirectUri"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
],
|
|
111
188
|
"form": null,
|
|
112
189
|
"display": null
|
|
113
190
|
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
<link rel="stylesheet" href="styles.css" />
|
|
2
|
+
|
|
3
|
+
<main class="container">
|
|
4
|
+
<header>
|
|
5
|
+
<h1>Nuheat Radiant Floor Heating</h1>
|
|
6
|
+
<p class="subtitle">
|
|
7
|
+
Configure MyNuheat account access, HomeKit accessory exposure, and
|
|
8
|
+
connection behavior.
|
|
9
|
+
</p>
|
|
10
|
+
</header>
|
|
11
|
+
|
|
12
|
+
<section class="panel">
|
|
13
|
+
<div class="section-header">
|
|
14
|
+
<div>
|
|
15
|
+
<h2>Account</h2>
|
|
16
|
+
<p class="help">
|
|
17
|
+
Most homes only need the MyNuheat email and password used by the
|
|
18
|
+
Nuheat mobile app or web portal.
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
<span id="auth-status" class="status-pill warn">Checking config</span>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="settings-grid">
|
|
25
|
+
<label class="field">
|
|
26
|
+
<span>Platform Name</span>
|
|
27
|
+
<input id="name" type="text" placeholder="NuHeat" />
|
|
28
|
+
<small>Name shown in Homebridge logs for this platform instance.</small>
|
|
29
|
+
</label>
|
|
30
|
+
|
|
31
|
+
<label class="field">
|
|
32
|
+
<span>MyNuheat Email</span>
|
|
33
|
+
<input id="email" type="email" placeholder="name@example.com" />
|
|
34
|
+
<small>Email address for the account that owns the thermostats.</small>
|
|
35
|
+
</label>
|
|
36
|
+
|
|
37
|
+
<label id="password-row" class="field">
|
|
38
|
+
<span>MyNuheat Password</span>
|
|
39
|
+
<input id="password" type="password" placeholder="Password" />
|
|
40
|
+
<small>Leave blank to keep an existing saved password.</small>
|
|
41
|
+
</label>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="actions">
|
|
45
|
+
<button id="save-account" class="primary">Save Account</button>
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
|
|
49
|
+
<section class="panel">
|
|
50
|
+
<div class="section-header">
|
|
51
|
+
<div>
|
|
52
|
+
<h2>Accessories</h2>
|
|
53
|
+
<p class="help">
|
|
54
|
+
Leave thermostat and group lists empty to use automatic discovery.
|
|
55
|
+
Add rows only when you want to limit what appears in HomeKit.
|
|
56
|
+
</p>
|
|
57
|
+
</div>
|
|
58
|
+
<span id="accessory-status" class="status-pill warn">Auto discovery</span>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="split-grid">
|
|
62
|
+
<div class="list-panel">
|
|
63
|
+
<div class="list-heading">
|
|
64
|
+
<div>
|
|
65
|
+
<h3>Thermostat Allow-List</h3>
|
|
66
|
+
<p class="help">
|
|
67
|
+
Optional serial numbers from MyNuheat.
|
|
68
|
+
</p>
|
|
69
|
+
</div>
|
|
70
|
+
<button id="add-device" class="secondary" type="button">Add</button>
|
|
71
|
+
</div>
|
|
72
|
+
<div id="devices-list" class="dynamic-list"></div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="list-panel">
|
|
76
|
+
<div class="list-heading">
|
|
77
|
+
<div>
|
|
78
|
+
<h3>Away Mode Groups</h3>
|
|
79
|
+
<p class="help">
|
|
80
|
+
Optional group names exactly as shown in MyNuheat.
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
<button id="add-group" class="secondary" type="button">Add</button>
|
|
84
|
+
</div>
|
|
85
|
+
<div id="groups-list" class="dynamic-list"></div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<label class="checkbox">
|
|
90
|
+
<input id="auto-populate-away-mode-switches" type="checkbox" />
|
|
91
|
+
<span>
|
|
92
|
+
Expose away-mode switches for all groups
|
|
93
|
+
<small>
|
|
94
|
+
Automatically creates HomeKit switches for every Nuheat group on the
|
|
95
|
+
account.
|
|
96
|
+
</small>
|
|
97
|
+
</span>
|
|
98
|
+
</label>
|
|
99
|
+
|
|
100
|
+
<label class="checkbox">
|
|
101
|
+
<input id="expose-schedule-switches" type="checkbox" />
|
|
102
|
+
<span>
|
|
103
|
+
Expose schedule switches
|
|
104
|
+
<small>
|
|
105
|
+
Adds one switch per thermostat that can resume the Nuheat schedule.
|
|
106
|
+
</small>
|
|
107
|
+
</span>
|
|
108
|
+
</label>
|
|
109
|
+
|
|
110
|
+
<div class="actions">
|
|
111
|
+
<button id="save-accessories" class="primary">Save Accessories</button>
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
115
|
+
<section class="panel">
|
|
116
|
+
<div class="section-header">
|
|
117
|
+
<div>
|
|
118
|
+
<h2>Behavior</h2>
|
|
119
|
+
<p class="help">
|
|
120
|
+
Tune setpoint holds, polling, Nuheat notifications, and debug logging.
|
|
121
|
+
</p>
|
|
122
|
+
</div>
|
|
123
|
+
<span id="behavior-status" class="status-pill good">Notifications on</span>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<div class="settings-grid">
|
|
127
|
+
<label class="field">
|
|
128
|
+
<span>Hold Length (minutes)</span>
|
|
129
|
+
<input id="hold-length" type="number" min="0" max="1440" step="1" />
|
|
130
|
+
<small>
|
|
131
|
+
0 holds until the next schedule event; 1440 creates a permanent hold.
|
|
132
|
+
</small>
|
|
133
|
+
</label>
|
|
134
|
+
|
|
135
|
+
<label class="field">
|
|
136
|
+
<span>Polling Interval (seconds)</span>
|
|
137
|
+
<input id="refresh" type="number" min="30" step="1" />
|
|
138
|
+
<small>
|
|
139
|
+
Polling is a safety net. Values below 30 are raised to 30 at runtime.
|
|
140
|
+
</small>
|
|
141
|
+
</label>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<label class="checkbox">
|
|
145
|
+
<input id="enable-notifications" type="checkbox" />
|
|
146
|
+
<span>
|
|
147
|
+
Enable Nuheat notifications
|
|
148
|
+
<small>
|
|
149
|
+
Uses SignalR notifications for faster updates. Disable only while
|
|
150
|
+
troubleshooting.
|
|
151
|
+
</small>
|
|
152
|
+
</span>
|
|
153
|
+
</label>
|
|
154
|
+
|
|
155
|
+
<label class="checkbox">
|
|
156
|
+
<input id="debug" type="checkbox" />
|
|
157
|
+
<span>
|
|
158
|
+
Enable debug logging
|
|
159
|
+
<small>
|
|
160
|
+
Writes verbose Nuheat API, notification, and accessory activity to the
|
|
161
|
+
Homebridge log.
|
|
162
|
+
</small>
|
|
163
|
+
</span>
|
|
164
|
+
</label>
|
|
165
|
+
|
|
166
|
+
<div class="actions">
|
|
167
|
+
<button id="save-behavior" class="primary">Save Behavior</button>
|
|
168
|
+
</div>
|
|
169
|
+
</section>
|
|
170
|
+
|
|
171
|
+
<section class="panel">
|
|
172
|
+
<div class="section-header">
|
|
173
|
+
<div>
|
|
174
|
+
<h2>Advanced OAuth</h2>
|
|
175
|
+
<p class="help">
|
|
176
|
+
Leave these fields blank unless Nuheat has issued confidential-client
|
|
177
|
+
credentials for testing. PKCE public-client support is planned but is
|
|
178
|
+
not active yet.
|
|
179
|
+
</p>
|
|
180
|
+
</div>
|
|
181
|
+
<span id="oauth-status" class="status-pill warn">Built-in fallback</span>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div class="settings-grid">
|
|
185
|
+
<label class="field">
|
|
186
|
+
<span>Nuheat Client ID</span>
|
|
187
|
+
<input id="client-id" type="text" placeholder="Optional client ID" />
|
|
188
|
+
<small>Advanced override for a Nuheat-issued OAuth client ID.</small>
|
|
189
|
+
</label>
|
|
190
|
+
|
|
191
|
+
<label id="client-secret-row" class="field">
|
|
192
|
+
<span>Nuheat Client Secret (Legacy)</span>
|
|
193
|
+
<input
|
|
194
|
+
id="client-secret"
|
|
195
|
+
type="password"
|
|
196
|
+
placeholder="Leave blank to keep existing"
|
|
197
|
+
/>
|
|
198
|
+
<small>
|
|
199
|
+
Required with a custom client ID until PKCE support ships. Do not
|
|
200
|
+
publish or share this value.
|
|
201
|
+
</small>
|
|
202
|
+
</label>
|
|
203
|
+
|
|
204
|
+
<label class="field">
|
|
205
|
+
<span>Nuheat Redirect URI</span>
|
|
206
|
+
<input id="redirect-uri" type="text" placeholder="http://localhost" />
|
|
207
|
+
<small>Defaults to http://localhost.</small>
|
|
208
|
+
</label>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div class="actions">
|
|
212
|
+
<button id="save-oauth" class="primary">Save OAuth Settings</button>
|
|
213
|
+
<button id="clear-oauth" class="secondary" type="button">
|
|
214
|
+
Clear Overrides
|
|
215
|
+
</button>
|
|
216
|
+
</div>
|
|
217
|
+
</section>
|
|
218
|
+
|
|
219
|
+
<section class="panel">
|
|
220
|
+
<div class="section-header">
|
|
221
|
+
<div>
|
|
222
|
+
<h2>Diagnostics</h2>
|
|
223
|
+
<p class="help">
|
|
224
|
+
Review the saved configuration and exposure strategy before
|
|
225
|
+
restarting Homebridge.
|
|
226
|
+
</p>
|
|
227
|
+
</div>
|
|
228
|
+
<button id="refresh-diagnostics" class="secondary" type="button">
|
|
229
|
+
Refresh
|
|
230
|
+
</button>
|
|
231
|
+
</div>
|
|
232
|
+
<div id="diagnostics-summary" class="diagnostics-summary muted">
|
|
233
|
+
No diagnostics loaded yet.
|
|
234
|
+
</div>
|
|
235
|
+
<div id="diagnostics-empty" class="help hidden">
|
|
236
|
+
Save settings to generate a configuration summary.
|
|
237
|
+
</div>
|
|
238
|
+
<div id="diagnostics-list" class="diagnostics-list"></div>
|
|
239
|
+
</section>
|
|
240
|
+
</main>
|
|
241
|
+
|
|
242
|
+
<div id="toast-container" class="toast-container"></div>
|
|
243
|
+
|
|
244
|
+
<script src="index.js"></script>
|