homebridge-withings-environment-data 1.5.0 → 1.6.2

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 CHANGED
@@ -6,6 +6,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## [1.6.2] - 2026-08-21
10
+
11
+ ### Changed
12
+ - Config UI: Authentication fieldset now starts collapsed
13
+ - Config UI: "Expose sensors as HomeKit Accessories" moved below the Air
14
+ Quality fieldset
15
+ - Host field's description now notes it defaults to port 1883 when the
16
+ port is omitted
17
+
18
+ ## [1.6.1] - 2026-08-21
19
+
20
+ ### Fixed
21
+ - Publish workflow's CI Node version bumped to 22 — the first real run
22
+ failed at `npm install -g npm@latest`, since the latest npm now
23
+ requires Node `^22.22.2 || ^24.15.0 || >=26.0.0` and the workflow had
24
+ pinned Node 20
25
+
26
+ ## [1.6.0] - 2026-08-21
27
+
28
+ ### Added
29
+ - "Requires authentication" checkbox in the MQTT fieldset; Username and
30
+ Password only appear (and are only sent to the broker) when it's checked
31
+
32
+ ### Changed
33
+ - MQTT Host and Port merged into a single "Host" field including the port,
34
+ e.g. `localhost:1883` (the new default)
35
+ - Publishing to npm now happens automatically via GitHub Actions on tagged
36
+ releases, using npm's OIDC trusted publishing (no npm tokens in CI)
37
+
9
38
  ## [1.5.0] - 2026-08-19
10
39
 
11
40
  ### Added
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Withings Environment Data v1.5.0
1
+ # Withings Environment Data v1.6.2
2
2
 
3
3
  **This Homebridge plugin has been 100% vibe coded with Claude.**
4
4
 
@@ -93,15 +93,17 @@ Fields:
93
93
  Anything above the Inferior boundary is reported as Poor.
94
94
  - **Expose sensors as HomeKit Accessories**: see [Usage](#usage) above.
95
95
  Default on.
96
- - **Publish to MQTT / Host / Port / Username / Password / Last Seen /
97
- Retain**: see [Usage](#usage) above. Publishing is off by default; Port
98
- defaults to 1883. Username/Password are optional, for brokers that
99
- require auth. **Last Seen** controls the format of the `last_seen`
100
- field, which always reflects the time the scale actually took the
101
- measurement (not when the plugin polled or published it): `ISO_8601`
102
- (default, UTC), `ISO_8601 local` (with UTC offset), `epoch`
103
- (milliseconds), or `disabled` to omit the field entirely. Retain is on
104
- by default.
96
+ - **Publish to MQTT / Host / Requires authentication / Username / Password /
97
+ Last Seen / Retain**: see [Usage](#usage) above. Publishing is off by
98
+ default. **Host** includes the port, e.g. `localhost:1883` (the
99
+ default); if the port is omitted it defaults to 1883. Username/Password
100
+ only apply, and only appear, when **Requires authentication** is
101
+ checked. **Last Seen** controls the
102
+ format of the `last_seen` field, which always reflects the time the
103
+ scale actually took the measurement (not when the plugin polled or
104
+ published it): `ISO_8601` (default, UTC), `ISO_8601 local` (with UTC
105
+ offset), `epoch` (milliseconds), or `disabled` to omit the field
106
+ entirely. Retain is on by default.
105
107
  - **Stale Data Warning Threshold (hours)**: if the newest reading from the
106
108
  scale itself (not the plugin's poll) is older than this many hours — e.g.
107
109
  nobody's stood on the scale in a while — a warning is logged on every
@@ -87,13 +87,12 @@
87
87
  "mqttHost": {
88
88
  "title": "Host",
89
89
  "type": "string",
90
- "default": "localhost",
91
- "description": "Broker hostname or IP address."
90
+ "default": "localhost:1883",
91
+ "description": "Broker hostname or IP address, including port. Defaults to port 1883 if the port is omitted."
92
92
  },
93
- "mqttPort": {
94
- "title": "Port",
95
- "type": "integer",
96
- "default": 1883
93
+ "mqttRequiresAuth": {
94
+ "title": "Requires authentication",
95
+ "type": "boolean"
97
96
  },
98
97
  "mqttUsername": {
99
98
  "title": "Username",
@@ -155,7 +154,7 @@
155
154
  "type": "fieldset",
156
155
  "title": "Authentication",
157
156
  "expandable": true,
158
- "expanded": true,
157
+ "expanded": false,
159
158
  "items": [
160
159
  "email",
161
160
  "password",
@@ -163,7 +162,6 @@
163
162
  "trustCookieValue"
164
163
  ]
165
164
  },
166
- "exposeAsHomekitAccessories",
167
165
  {
168
166
  "type": "fieldset",
169
167
  "title": "MQTT",
@@ -172,9 +170,19 @@
172
170
  "items": [
173
171
  "publishToMqtt",
174
172
  "mqttHost",
175
- "mqttPort",
176
- "mqttUsername",
177
- "mqttPassword",
173
+ "mqttRequiresAuth",
174
+ {
175
+ "key": "mqttUsername",
176
+ "condition": {
177
+ "functionBody": "return model.mqttRequiresAuth === true;"
178
+ }
179
+ },
180
+ {
181
+ "key": "mqttPassword",
182
+ "condition": {
183
+ "functionBody": "return model.mqttRequiresAuth === true;"
184
+ }
185
+ },
178
186
  "mqttLastSeen",
179
187
  "mqttRetain"
180
188
  ]
@@ -192,6 +200,7 @@
192
200
  "airQualityInferiorMaxPpm"
193
201
  ]
194
202
  },
203
+ "exposeAsHomekitAccessories",
195
204
  "pollIntervalMinutes",
196
205
  "noResponseAfterMissedPolls",
197
206
  "staleDataWarningThresholdHours",
package/index.js CHANGED
@@ -256,19 +256,38 @@ class WithingsEnvironmentDataPlatform {
256
256
  return this.config.publishToMqtt === true;
257
257
  }
258
258
 
259
+ // mqttHost is a single "host[:port]" field; older configs saved before that
260
+ // merge may still have a separate mqttPort value sitting in config.json
261
+ // (config UI stops writing it once resaved, but doesn't retroactively
262
+ // delete it), so fall back to that before the hardcoded default.
263
+ getMqttHostAndPort() {
264
+ const raw = this.config.mqttHost || '';
265
+ const colonIndex = raw.lastIndexOf(':');
266
+ if (colonIndex > -1) {
267
+ const host = raw.slice(0, colonIndex);
268
+ const port = Number(raw.slice(colonIndex + 1));
269
+ if (host && Number.isFinite(port) && port > 0) {
270
+ return { host, port };
271
+ }
272
+ }
273
+ const legacyPort = Number(this.config.mqttPort);
274
+ return { host: raw, port: Number.isFinite(legacyPort) && legacyPort > 0 ? legacyPort : 1883 };
275
+ }
276
+
259
277
  connectMqtt() {
260
278
  if (!this.getPublishToMqtt()) return;
261
279
 
262
- if (!this.config.mqttHost) {
280
+ const { host, port } = this.getMqttHostAndPort();
281
+ if (!host) {
263
282
  this.log.warn('Publish to MQTT is enabled but no MQTT Host is configured; MQTT publishing is disabled.');
264
283
  return;
265
284
  }
266
285
 
267
- const port = Number(this.config.mqttPort);
268
- const url = `mqtt://${this.config.mqttHost}:${Number.isFinite(port) && port > 0 ? port : 1883}`;
286
+ const url = `mqtt://${host}:${port}`;
287
+ const requiresAuth = this.config.mqttRequiresAuth === true;
269
288
  this.mqttClient = mqtt.connect(url, {
270
- username: this.config.mqttUsername || undefined,
271
- password: this.config.mqttPassword || undefined,
289
+ username: requiresAuth ? this.config.mqttUsername || undefined : undefined,
290
+ password: requiresAuth ? this.config.mqttPassword || undefined : undefined,
272
291
  });
273
292
  this.mqttClient.on('error', (err) => this.log.warn(`MQTT connection error: ${err.message}`));
274
293
  // Without this, a silently-never-connecting client looks identical in the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-withings-environment-data",
3
3
  "displayName": "Withings Environment Data",
4
- "version": "1.5.0",
4
+ "version": "1.6.2",
5
5
  "description": "Homebridge plugin exposing ambient CO2/air-quality and room temperature readings from a Withings WS-50 scale as HomeKit sensors",
6
6
  "main": "index.js",
7
7
  "files": [