homebridge-openwrt-control 0.4.0 → 0.4.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 +13 -0
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/hadiscovery.js +25 -5
- package/src/mqtt.js +5 -0
- package/src/router.js +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- After update to v0.1.0 the plugin need to be reconfigured!
|
|
11
11
|
|
|
12
|
+
## [0.4.2] - (29.09.2026)
|
|
13
|
+
|
|
14
|
+
### Changes
|
|
15
|
+
|
|
16
|
+
- fixed: Home Assistant discovery, the config and the state are published again after a restart of the broker, a broker without persistence loses the retained messages
|
|
17
|
+
|
|
18
|
+
## [0.4.1] - (25.09.2026)
|
|
19
|
+
|
|
20
|
+
### Changes
|
|
21
|
+
|
|
22
|
+
- fix: Home Assistant radio entities had the same name on routers with two radios of one band (two `Wi-Fi 5 GHz`), radios are now named by band and radio number (`5 GHz Radio 0`, `Restart 5 GHz Radio 0`, `Channel 5 GHz Radio 0`), SSIDs get the radio added when the same network is on two radios of one band (`Dom 5 GHz Radio 2`). Entity ids do not change
|
|
23
|
+
- readme update
|
|
24
|
+
|
|
12
25
|
## [0.4.0] - (25.09.2026)
|
|
13
26
|
|
|
14
27
|
### Changes
|
package/README.md
CHANGED
|
@@ -154,12 +154,12 @@ With `mqtt.haDiscovery` the router appears in Home Assistant as one device with
|
|
|
154
154
|
| Entity | Type | Description |
|
|
155
155
|
| --- | --- | --- |
|
|
156
156
|
| `WAN` | binary_sensor (connectivity) | WAN interface up, `Internet` on routers without a `wan` interface |
|
|
157
|
-
| `
|
|
158
|
-
| `<SSID> <band>` | switch | SSID on/off |
|
|
159
|
-
| `Restart
|
|
157
|
+
| `2.4 GHz Radio 0`, `5 GHz Radio 1`... | switch | Radio on/off, named by band and radio number |
|
|
158
|
+
| `<SSID> <band>` | switch | SSID on/off, the radio is added (`Dom 5 GHz Radio 2`) when the same network is on two radios of one band |
|
|
159
|
+
| `Restart <band> Radio <n>` | button (restart) | Radio restart |
|
|
160
160
|
| `Reboot`, `Reload network`, `Reload Wi-Fi` | button | System reboot, network and wireless reload |
|
|
161
161
|
| `Wi-Fi clients`, `<SSID> <band> clients` | sensor | Connected clients, total and per SSID |
|
|
162
|
-
| `Channel <band>`, `TX power <band>` | sensor (diagnostic) | Current radio channel and TX power in dBm |
|
|
162
|
+
| `Channel <band> Radio <n>`, `TX power <band> Radio <n>` | sensor (diagnostic) | Current radio channel and TX power in dBm |
|
|
163
163
|
| `WAN IP`, `Firmware`, `Last boot`, `Load`, `Memory usage` | sensor (diagnostic) | System information |
|
|
164
164
|
| `<SSID> <band> QR code` | image | QR code to join the network, only with `mqtt.haWifiQr` |
|
|
165
165
|
|
package/package.json
CHANGED
package/src/hadiscovery.js
CHANGED
|
@@ -53,6 +53,13 @@ class HaDiscovery {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// The broker may have lost the retained messages (restart without persistence), the next sync sends everything again
|
|
57
|
+
reset() {
|
|
58
|
+
this.lastConfig = {};
|
|
59
|
+
this.lastState = '';
|
|
60
|
+
this.lastImage = {};
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
has(suffix, available) {
|
|
57
64
|
if (available) this.seen.add(suffix);
|
|
58
65
|
return this.seen.has(suffix);
|
|
@@ -164,25 +171,30 @@ class HaDiscovery {
|
|
|
164
171
|
button('network_reload', { NetworkReload: true }, { name: 'Reload network', icon: 'mdi:lan-pending', entity_category: 'config' });
|
|
165
172
|
button('wireless_reload', { WirelessReload: true }, { name: 'Reload Wi-Fi', icon: 'mdi:wifi-refresh', entity_category: 'config' });
|
|
166
173
|
|
|
167
|
-
// Radios
|
|
174
|
+
// Radios, named by band and radio number (5 GHz Radio 0), tri-band routers have two radios of one band
|
|
168
175
|
for (const radio of info.wirelessRadios ?? []) {
|
|
169
176
|
const id = radio.name;
|
|
170
177
|
const key = this.key(id);
|
|
171
|
-
const label =
|
|
178
|
+
const label = this.radioLabel(radio);
|
|
172
179
|
const radioInfo = ext.radios?.[id] ?? {};
|
|
173
|
-
toggle(`radio_${key}`, id, 'Radio', { name:
|
|
174
|
-
button(`radio_${key}_restart`, { RadioRestart: { id } }, { name: `Restart
|
|
180
|
+
toggle(`radio_${key}`, id, 'Radio', { name: label, icon: 'mdi:wifi', value_template: `{{ 'ON' if value_json.radios['${id}'].on else 'OFF' }}` });
|
|
181
|
+
button(`radio_${key}_restart`, { RadioRestart: { id } }, { name: `Restart ${label}`, device_class: 'restart', entity_category: 'config' });
|
|
175
182
|
if (this.has(`radio_${key}_channel`, radioInfo.channel != null)) sensor(`radio_${key}_channel`, { name: `Channel ${label}`, icon: 'mdi:access-point', entity_category: 'diagnostic', value_template: state(`.radios['${id}'].channel`) });
|
|
176
183
|
if (this.has(`radio_${key}_txpower`, radioInfo.txpower != null)) sensor(`radio_${key}_txpower`, { name: `TX power ${label}`, icon: 'mdi:signal', unit_of_measurement: 'dBm', state_class: 'measurement', entity_category: 'diagnostic', value_template: state(`.radios['${id}'].txpower`) });
|
|
177
184
|
}
|
|
178
185
|
|
|
179
186
|
// SSIDs, the id is the UCI section so renaming the network keeps the entity
|
|
187
|
+
// SSIDs named by network and band (Dom 5 GHz), the radio is added when the same network is on two radios of one band
|
|
180
188
|
const uci = info.wirelessInfo?.values ?? {};
|
|
189
|
+
const ssidBand = (ssid) => `${ssid.name} ${BandLabel[ssid.band] ?? ssid.radio ?? ''}`.trim();
|
|
190
|
+
const ssidLabels = (info.wirelessSsids ?? []).map(ssidBand);
|
|
181
191
|
for (const ssid of info.wirelessSsids ?? []) {
|
|
182
192
|
if (!ssid.section || !ssid.name) continue;
|
|
183
193
|
const id = ssid.section;
|
|
184
194
|
const key = this.key(id);
|
|
185
|
-
const
|
|
195
|
+
const radio = (info.wirelessRadios ?? []).find(r => r.name === ssid.radio);
|
|
196
|
+
const duplicate = ssidLabels.filter(label => label === ssidBand(ssid)).length > 1;
|
|
197
|
+
const label = duplicate && radio ? `${ssid.name} ${this.radioLabel(radio)}` : ssidBand(ssid);
|
|
186
198
|
toggle(`ssid_${key}`, id, 'Ssid', { name: label, icon: 'mdi:wifi-lock', value_template: `{{ 'ON' if value_json.ssids['${id}'].on else 'OFF' }}` });
|
|
187
199
|
if (clientsAvailable && (ssid.mode ?? 'ap') === 'ap') sensor(`ssid_${key}_clients`, { name: `${label} clients`, icon: 'mdi:account-multiple', state_class: 'measurement', value_template: state(`.ssids['${id}'].clients`) });
|
|
188
200
|
|
|
@@ -248,6 +260,14 @@ class HaDiscovery {
|
|
|
248
260
|
return qr.createSvgTag({ cellSize: 8, margin: 4, scalable: true });
|
|
249
261
|
}
|
|
250
262
|
|
|
263
|
+
// 5 GHz Radio 0, the number from the radio name (radio0), other names as they are
|
|
264
|
+
radioLabel(radio) {
|
|
265
|
+
const number = String(radio.name).match(/^radio(\d+)$/)?.[1];
|
|
266
|
+
const band = BandLabel[radio.band];
|
|
267
|
+
const name = number !== undefined ? `Radio ${number}` : radio.name;
|
|
268
|
+
return band ? `${band} ${name}` : name;
|
|
269
|
+
}
|
|
270
|
+
|
|
251
271
|
// Object id part of a radio or UCI section name
|
|
252
272
|
key(id) {
|
|
253
273
|
return String(id).replace(/[^a-zA-Z0-9_-]/g, '_');
|
package/src/mqtt.js
CHANGED
|
@@ -36,6 +36,7 @@ class Mqtt extends EventEmitter {
|
|
|
36
36
|
} : {})
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
this.connected = false;
|
|
39
40
|
const startTime = Date.now();
|
|
40
41
|
let hasConnected = false;
|
|
41
42
|
let warnedStalled = false;
|
|
@@ -45,6 +46,9 @@ class Mqtt extends EventEmitter {
|
|
|
45
46
|
hasConnected = true;
|
|
46
47
|
this.emit('connected', `MQTT v${protocolVersion} connected.`);
|
|
47
48
|
if (this.haDiscovery) this.publishRetained(this.availabilityTopic, 'online').catch(() => { });
|
|
49
|
+
// Every connect, also when the broker was not running at start or restarted, devices publish again
|
|
50
|
+
this.connected = true;
|
|
51
|
+
this.emit('online');
|
|
48
52
|
|
|
49
53
|
try {
|
|
50
54
|
await new Promise((resolve, reject) => {
|
|
@@ -90,6 +94,7 @@ class Mqtt extends EventEmitter {
|
|
|
90
94
|
if (config.logDebug) this.emit('debug', 'MQTT Reconnecting...');
|
|
91
95
|
})
|
|
92
96
|
.on('close', () => {
|
|
97
|
+
this.connected = false;
|
|
93
98
|
if (!hasConnected && !warnedStalled && Date.now() - startTime > 30000) {
|
|
94
99
|
warnedStalled = true;
|
|
95
100
|
this.emit('warn', `MQTT has not connected after 30s of retries using protocol v${protocolVersion}. Check broker address, credentials, and whether the broker supports this MQTT protocol version.`);
|
package/src/router.js
CHANGED
|
@@ -224,6 +224,11 @@ class Router extends EventEmitter {
|
|
|
224
224
|
.on('connected', msg => {
|
|
225
225
|
this.mqttConnected = true;
|
|
226
226
|
this.emit('success', msg);
|
|
227
|
+
})
|
|
228
|
+
.on('online', () => {
|
|
229
|
+
// Every connect, the broker may have lost the retained messages after a restart
|
|
230
|
+
this.mqttConnected = true;
|
|
231
|
+
this.ha?.reset();
|
|
227
232
|
this.haSync();
|
|
228
233
|
})
|
|
229
234
|
.on('set', async (key, value) => {
|