homebridge-openwrt-control 0.0.2-beta.4 → 0.0.2-beta.41
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/config.schema.json +2 -2
- package/index.js +37 -39
- package/package.json +1 -1
- package/src/{apdevice.js → accesspoint.js} +26 -22
- package/src/openwrt.js +56 -57
- package/src/{swdevice.js → switch.js} +36 -28
package/config.schema.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"singular": true,
|
|
5
5
|
"fixArrays": true,
|
|
6
6
|
"strictValidation": true,
|
|
7
|
-
"headerDisplay": "This plugin works with OpenWrt
|
|
7
|
+
"headerDisplay": "This plugin works with OpenWrt flashed devices. Devices are exposed to HomeKit as separate accessories and each needs to be manually paired.",
|
|
8
8
|
"footerDisplay": "For documentation please see [GitHub repository](https://github.com/grzegorz914/homebridge-openwrt-control).",
|
|
9
9
|
"schema": {
|
|
10
10
|
"type": "object",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"type": "array",
|
|
14
14
|
"items": {
|
|
15
15
|
"type": "object",
|
|
16
|
-
"title": "
|
|
16
|
+
"title": "Device",
|
|
17
17
|
"properties": {
|
|
18
18
|
"name": {
|
|
19
19
|
"title": "Name",
|
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
3
3
|
import OpenWrt from './src/openwrt.js';
|
|
4
|
-
import AccessPoint from './src/
|
|
5
|
-
import Switch from './src/
|
|
4
|
+
import AccessPoint from './src/accesspoint.js';
|
|
5
|
+
import Switch from './src/switch.js';
|
|
6
6
|
import ImpulseGenerator from './src/impulsegenerator.js';
|
|
7
7
|
import { PluginName, PlatformName } from './src/constants.js';
|
|
8
8
|
|
|
@@ -14,7 +14,6 @@ class OpenWrtPlatform {
|
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
this.accessories = [];
|
|
17
|
-
this.devices = [];
|
|
18
17
|
|
|
19
18
|
//check if prefs directory exist
|
|
20
19
|
const prefDir = join(api.user.storagePath(), 'openWrt');
|
|
@@ -27,9 +26,9 @@ class OpenWrtPlatform {
|
|
|
27
26
|
|
|
28
27
|
api.on('didFinishLaunching', async () => {
|
|
29
28
|
for (const deviceConfig of config.devices) {
|
|
30
|
-
const { name, host,
|
|
31
|
-
if (!name || !host || !
|
|
32
|
-
log.warn(`Device: ${host || 'host missing'}, ${name || 'name missing'}, ${
|
|
29
|
+
const { name, host, displayType } = deviceConfig;
|
|
30
|
+
if (!name || !host || !displayType) {
|
|
31
|
+
log.warn(`Device: ${host || 'host missing'}, ${name || 'name missing'}, ${!displayType ? ', display type disabled' : ''} in config, will not be published in the Home app`);
|
|
33
32
|
continue;
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -61,43 +60,45 @@ class OpenWrtPlatform {
|
|
|
61
60
|
log.info(`Device: ${host} ${name}, Config: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
62
61
|
}
|
|
63
62
|
|
|
63
|
+
const configuredDevices = [];
|
|
64
64
|
const refreshInterval = (deviceConfig.refreshInterval ?? 5) * 1000;
|
|
65
|
-
if (deviceConfig.accessPoint?.enable)
|
|
66
|
-
if (deviceConfig.switch?.enable)
|
|
67
|
-
|
|
68
|
-
if (this.devices.length === 0) return;
|
|
69
|
-
|
|
70
|
-
const openWrt = new OpenWrt(deviceConfig)
|
|
71
|
-
.on('success', msg => logLevel.success && log.success(`Device: ${host}, ${msg}`))
|
|
72
|
-
.on('info', msg => log.info(`Device: ${host}, ${msg}`))
|
|
73
|
-
.on('debug', msg => log.info(`Device: ${host}, debug: ${msg}`))
|
|
74
|
-
.on('warn', msg => log.warn(`Device: ${host}, ${msg}`))
|
|
75
|
-
.on('error', msg => log.error(`Device: ${host}, ${msg}`))
|
|
76
|
-
|
|
77
|
-
const openWrtInfo = await openWrt.connect();
|
|
78
|
-
if (!openWrtInfo.state) {
|
|
79
|
-
if (logLevel.warn) log.warn(`Device: ${host} ${name}, no data received`);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
65
|
+
if (deviceConfig.accessPoint?.enable) configuredDevices.push('accessPoint');
|
|
66
|
+
if (deviceConfig.switch?.enable) configuredDevices.push('switch');
|
|
67
|
+
if (configuredDevices.length === 0) continue;
|
|
82
68
|
|
|
83
69
|
try {
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
const openWrt = new OpenWrt(deviceConfig)
|
|
71
|
+
.on('success', msg => logLevel.success && log.success(`Device: ${host}, ${msg}`))
|
|
72
|
+
.on('info', msg => log.info(`Device: ${host} ${name}, ${msg}`))
|
|
73
|
+
.on('debug', msg => log.info(`Device: ${host} ${name}, debug: ${msg}`))
|
|
74
|
+
.on('warn', msg => log.warn(`Device: ${host} ${name}, ${msg}`))
|
|
75
|
+
.on('error', msg => log.error(`Device: ${host} ${name}, ${msg}`))
|
|
76
|
+
|
|
77
|
+
const openWrtInfo = await openWrt.connect();
|
|
78
|
+
if (!openWrtInfo.state) {
|
|
79
|
+
if (logLevel.warn) log.warn(`Device: ${host} ${name}, no data received`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// start openwrt impulse generator
|
|
84
|
+
await openWrt.impulseGenerator.state(true, [{ name: 'connect', sampling: refreshInterval }], false);
|
|
85
|
+
|
|
86
|
+
// create impulse generator for every device
|
|
87
|
+
for (const device of configuredDevices) {
|
|
86
88
|
const impulseGenerator = new ImpulseGenerator()
|
|
87
89
|
.on('start', async () => {
|
|
88
90
|
try {
|
|
89
91
|
|
|
90
|
-
// create device
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return;
|
|
92
|
+
// create device clases
|
|
93
|
+
const DeviceClasses = { accessPoint: AccessPoint, switch: Switch };
|
|
94
|
+
const DeviceClass = DeviceClasses[device];
|
|
95
|
+
|
|
96
|
+
if (!DeviceClass) {
|
|
97
|
+
if (logLevel.warn) log.warn(`Device: ${host} ${name}, class not found for: ${device}`);
|
|
98
|
+
return;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
type
|
|
101
|
+
const type = new DeviceClass(api, deviceConfig, openWrt, openWrtInfo)
|
|
101
102
|
.on('devInfo', msg => logLevel.devInfo && log.info(msg))
|
|
102
103
|
.on('success', msg => logLevel.success && log.success(`Device: ${host} ${name}, ${msg}`))
|
|
103
104
|
.on('info', msg => log.info(`Device: ${host} ${name}, ${msg}`))
|
|
@@ -111,7 +112,7 @@ class OpenWrtPlatform {
|
|
|
111
112
|
if (logLevel.success) log.success(`Device: ${host} ${name}, Published as external accessory.`);
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
// stop
|
|
115
|
+
// stop accessory impulse generator
|
|
115
116
|
await impulseGenerator.state(false);
|
|
116
117
|
} catch (error) {
|
|
117
118
|
if (logLevel.error) log.error(`Device: ${host} ${name}, Start impulse generator error: ${error.message ?? error}, trying again.`);
|
|
@@ -121,12 +122,9 @@ class OpenWrtPlatform {
|
|
|
121
122
|
if (logLevel.debug) log.info(`Device: ${host} ${name}, Start impulse generator ${state ? 'started' : 'stopped'}.`);
|
|
122
123
|
});
|
|
123
124
|
|
|
124
|
-
// start impulse generator
|
|
125
|
+
// start accessory impulse generator
|
|
125
126
|
await impulseGenerator.state(true, [{ name: 'start', sampling: 120000 }]);
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
-
// start openwrt impulse generator
|
|
129
|
-
await openWrt.impulseGenerator.state(true, [{ name: 'connect', sampling: refreshInterval }], false);
|
|
130
128
|
} catch (error) {
|
|
131
129
|
if (logLevel.error) log.error(`Device: ${host} ${name}, Did finish launching error: ${error.message ?? error}`);
|
|
132
130
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class AccessPoint extends EventEmitter {
|
|
5
5
|
constructor(api, config, openWrt, openWrtInfo) {
|
|
6
6
|
super();
|
|
7
7
|
|
|
@@ -12,6 +12,7 @@ class AccessPointDevice extends EventEmitter {
|
|
|
12
12
|
AccessoryUUID = api.hap.uuid;
|
|
13
13
|
|
|
14
14
|
//config
|
|
15
|
+
this.host = config.host;
|
|
15
16
|
this.name = config.accessPoint.name || openWrtInfo.systemInfo.hostname;
|
|
16
17
|
this.accessPoint = config.accessPoint;
|
|
17
18
|
this.logInfo = config.log?.info || false;
|
|
@@ -65,8 +66,8 @@ class AccessPointDevice extends EventEmitter {
|
|
|
65
66
|
this.mqtt1 = new Mqtt({
|
|
66
67
|
host: this.mqtt.host,
|
|
67
68
|
port: this.mqtt.port || 1883,
|
|
68
|
-
clientId: this.mqtt.clientId ? `${this.
|
|
69
|
-
prefix: this.mqtt.prefix ? `${this.
|
|
69
|
+
clientId: this.mqtt.clientId ? `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}_${this.mqtt.clientId}_${Math.random().toString(16).slice(3)}` : `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}_${Math.random().toString(16).slice(3)}`,
|
|
70
|
+
prefix: this.mqtt.prefix ? `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}/${this.mqtt.prefix}/${this.name}` : `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}/${this.name}`,
|
|
70
71
|
user: this.mqtt.auth?.user,
|
|
71
72
|
passwd: this.mqtt.auth?.passwd,
|
|
72
73
|
logWarn: this.logWarn,
|
|
@@ -121,23 +122,23 @@ class AccessPointDevice extends EventEmitter {
|
|
|
121
122
|
//prepare accessory
|
|
122
123
|
if (this.logDebug) this.emit('debug', `prepare accessory`);
|
|
123
124
|
const accessoryName = this.name;
|
|
124
|
-
const accessoryUUID = AccessoryUUID.generate(this.openWrtInfo.systemInfo.
|
|
125
|
+
const accessoryUUID = AccessoryUUID.generate(this.host + this.openWrtInfo.systemInfo.system);
|
|
125
126
|
const accessoryCategory = Categories.AIRPORT;
|
|
126
127
|
const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
|
|
127
128
|
|
|
128
129
|
//prepare information service
|
|
129
130
|
if (this.logDebug) this.emit('debug', `prepare information service`);
|
|
130
|
-
accessory.getService(Service.AccessoryInformation)
|
|
131
|
-
.setCharacteristic(Characteristic.Manufacturer, 'OpenWrt')
|
|
131
|
+
this.informationService = accessory.getService(Service.AccessoryInformation)
|
|
132
|
+
.setCharacteristic(Characteristic.Manufacturer, this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt')
|
|
132
133
|
.setCharacteristic(Characteristic.Model, this.openWrtInfo.systemInfo.model)
|
|
133
134
|
.setCharacteristic(Characteristic.SerialNumber, this.openWrtInfo.systemInfo.system)
|
|
134
|
-
.setCharacteristic(Characteristic.FirmwareRevision, this.openWrtInfo.systemInfo.release?.
|
|
135
|
-
.setCharacteristic(Characteristic.ConfiguredName, accessoryName);
|
|
135
|
+
.setCharacteristic(Characteristic.FirmwareRevision, this.openWrtInfo.systemInfo.release?.version);
|
|
136
136
|
|
|
137
137
|
if (this.logDebug) this.emit('debug', `prepare service`);
|
|
138
138
|
|
|
139
|
-
//
|
|
139
|
+
//services
|
|
140
140
|
this.services = [];
|
|
141
|
+
this.sensorServices = [];
|
|
141
142
|
for (const ssid of this.ssids) {
|
|
142
143
|
const name = ssid.name;
|
|
143
144
|
if (this.logDebug) this.emit('debug', `prepare ssid: ${name} service`);
|
|
@@ -165,8 +166,6 @@ class AccessPointDevice extends EventEmitter {
|
|
|
165
166
|
|
|
166
167
|
if (this.accessPoint.sensor) {
|
|
167
168
|
if (this.logDebug) this.emit('debug', `prepare ssid: ${name} sensor service`);
|
|
168
|
-
|
|
169
|
-
this.sensorServices = [];
|
|
170
169
|
const sensorService = accessory.addService(Service.ContactSensor, serviceName, `sensorService${name}`);
|
|
171
170
|
sensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
|
|
172
171
|
sensorService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
|
|
@@ -192,39 +191,44 @@ class AccessPointDevice extends EventEmitter {
|
|
|
192
191
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
193
192
|
|
|
194
193
|
this.emit('devInfo', `-------- Access Point ${this.name} --------`);
|
|
195
|
-
this.emit('devInfo', `
|
|
196
|
-
this.emit('devInfo', `Model: ${this.openWrtInfo.systemInfo.model}`);
|
|
194
|
+
this.emit('devInfo', `Model: ${this.openWrtInfo.systemInfo.model || this.openWrtInfo.systemInfo.board_name}`);
|
|
197
195
|
this.emit('devInfo', `System: ${this.openWrtInfo.systemInfo.system}`);
|
|
196
|
+
this.emit('devInfo', `Kernel: ${this.openWrtInfo.systemInfo.kernel}`);
|
|
198
197
|
this.emit('devInfo', `Firmware: ${this.openWrtInfo.systemInfo.release?.description}`);
|
|
198
|
+
this.emit('devInfo', `Target: ${this.openWrtInfo.systemInfo.release?.target}`);
|
|
199
|
+
this.emit('devInfo', `SSIDs: ${this.ssids.length}`);
|
|
199
200
|
this.emit('devInfo', `----------------------------------`);
|
|
200
201
|
|
|
201
202
|
//openwrt client
|
|
202
203
|
this.openWrt.on('systemInfo', (info) => {
|
|
203
|
-
this.informationService?.updateCharacteristic(Characteristic.FirmwareRevision, info.release?.
|
|
204
|
+
this.informationService?.updateCharacteristic(Characteristic.FirmwareRevision, info.release?.version);
|
|
204
205
|
})
|
|
206
|
+
.on('networkInfo', async (info) => {
|
|
207
|
+
})
|
|
205
208
|
.on('wirelessStatus', async (status) => {
|
|
206
209
|
})
|
|
207
210
|
.on('wirelessRadios', async (radios) => {
|
|
208
211
|
})
|
|
209
212
|
.on('ssids', async (ssids) => {
|
|
213
|
+
this.ssids = ssids;
|
|
214
|
+
|
|
210
215
|
// sensors
|
|
211
216
|
for (let i = 0; i < ssids.length; i++) {
|
|
212
217
|
const ssid = ssids[i];
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
const state = ssid[i].state;
|
|
218
|
+
const name = ssid.name;
|
|
219
|
+
const state = ssid.state;
|
|
216
220
|
const serviceName = this.accessPoint.namePrefix ? `${this.name} ${name}` : name;
|
|
217
221
|
this.services?.[i]
|
|
218
222
|
?.setCharacteristic(Characteristic.ConfiguredName, serviceName)
|
|
219
223
|
.updateCharacteristic(Characteristic.On, state);
|
|
220
224
|
|
|
221
225
|
this.sensorServices?.[i]
|
|
222
|
-
?.setCharacteristic(Characteristic.ConfiguredName,
|
|
223
|
-
.updateCharacteristic(Characteristic.ContactSensorState, state
|
|
226
|
+
?.setCharacteristic(Characteristic.ConfiguredName, serviceName)
|
|
227
|
+
.updateCharacteristic(Characteristic.ContactSensorState, !state);
|
|
224
228
|
|
|
225
229
|
if (this.logInfo) {
|
|
226
|
-
this.emit('info', `
|
|
227
|
-
this.emit('info', `
|
|
230
|
+
this.emit('info', `Name: ${ssid.name}`);
|
|
231
|
+
this.emit('info', `State: ${ssid.state}`);
|
|
228
232
|
this.emit('info', `Mode: ${ssid.mode}`);
|
|
229
233
|
}
|
|
230
234
|
}
|
|
@@ -244,4 +248,4 @@ class AccessPointDevice extends EventEmitter {
|
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
250
|
};
|
|
247
|
-
export default
|
|
251
|
+
export default AccessPoint;
|
package/src/openwrt.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import EventEmitter from
|
|
2
|
-
import axios from
|
|
1
|
+
import EventEmitter from 'events';
|
|
2
|
+
import axios from 'axios';
|
|
3
3
|
import Functions from './functions.js';
|
|
4
|
-
import ImpulseGenerator from
|
|
4
|
+
import ImpulseGenerator from './impulsegenerator.js';
|
|
5
5
|
|
|
6
6
|
class OpenWrt extends EventEmitter {
|
|
7
7
|
constructor(config) {
|
|
8
8
|
super();
|
|
9
9
|
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.user = config.user;
|
|
13
|
-
this.passwd = config.passwd;
|
|
10
|
+
this.user = config.auth?.user || 'root';
|
|
11
|
+
this.passwd = config.auth?.passwd;
|
|
14
12
|
this.logError = config.log?.error;
|
|
15
13
|
this.logDebug = config.log?.debug;
|
|
16
14
|
|
|
@@ -26,7 +24,7 @@ class OpenWrt extends EventEmitter {
|
|
|
26
24
|
|
|
27
25
|
this.functions = new Functions();
|
|
28
26
|
this.axiosInstance = axios.create({
|
|
29
|
-
baseURL:
|
|
27
|
+
baseURL: `http://${config.host}/ubus`,
|
|
30
28
|
timeout: 5000,
|
|
31
29
|
headers: {
|
|
32
30
|
"Content-Type": "application/json"
|
|
@@ -34,11 +32,11 @@ class OpenWrt extends EventEmitter {
|
|
|
34
32
|
});
|
|
35
33
|
|
|
36
34
|
this.impulseGenerator = new ImpulseGenerator()
|
|
37
|
-
.on(
|
|
35
|
+
.on('connect', () => this.handleWithLock(async () => {
|
|
38
36
|
await this.connect();
|
|
39
37
|
}))
|
|
40
|
-
.on(
|
|
41
|
-
this.emit(state ?
|
|
38
|
+
.on('state', (state) => {
|
|
39
|
+
this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
|
|
42
40
|
});
|
|
43
41
|
}
|
|
44
42
|
|
|
@@ -49,8 +47,7 @@ class OpenWrt extends EventEmitter {
|
|
|
49
47
|
try {
|
|
50
48
|
await fn();
|
|
51
49
|
} catch (error) {
|
|
52
|
-
this.emit(
|
|
53
|
-
);
|
|
50
|
+
this.emit('error', `Impulse generator error: ${error.message}`);
|
|
54
51
|
} finally {
|
|
55
52
|
this.lock = false;
|
|
56
53
|
}
|
|
@@ -62,52 +59,53 @@ class OpenWrt extends EventEmitter {
|
|
|
62
59
|
return this.sessionId;
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
const response = await this.axiosInstance.post(
|
|
66
|
-
jsonrpc:
|
|
62
|
+
const response = await this.axiosInstance.post('', {
|
|
63
|
+
jsonrpc: '2.0',
|
|
67
64
|
id: 1,
|
|
68
|
-
method:
|
|
69
|
-
params: [
|
|
65
|
+
method: 'call',
|
|
66
|
+
params: ['00000000000000000000000000000000', 'session', 'login', { username: this.user, password: this.passwd }]
|
|
70
67
|
});
|
|
71
68
|
|
|
72
69
|
const result = response.data?.result?.[1];
|
|
73
|
-
if (!result?.ubus_rpc_session)
|
|
74
|
-
throw new Error("ubus login failed");
|
|
75
|
-
}
|
|
70
|
+
if (!result?.ubus_rpc_session) throw new Error('Ubus login failed');
|
|
76
71
|
|
|
77
72
|
this.sessionId = result.ubus_rpc_session;
|
|
78
73
|
this.sessionExpiresAt = now + 240_000;
|
|
79
74
|
|
|
80
|
-
if (this.logDebug) this.emit(
|
|
75
|
+
if (this.logDebug) this.emit('debug', `Ubus login OK`);
|
|
81
76
|
return this.sessionId;
|
|
82
77
|
}
|
|
83
78
|
|
|
84
79
|
async ubusCall(service, method, params = {}) {
|
|
85
80
|
const session = await this.login();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
jsonrpc: "2.0",
|
|
81
|
+
const response = await this.axiosInstance.post('', {
|
|
82
|
+
jsonrpc: '2.0',
|
|
89
83
|
id: 2,
|
|
90
|
-
method:
|
|
84
|
+
method: 'call',
|
|
91
85
|
params: [session, service, method, params]
|
|
92
86
|
});
|
|
93
87
|
|
|
94
|
-
if (response.data
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
if (this.logDebug) this.emit('debug', `Response: ${JSON.stringify(response.data, null, 2)}`);
|
|
89
|
+
|
|
90
|
+
if (response.data?.error) throw new Error(response.data.error.message || 'Ubus call error');
|
|
97
91
|
|
|
98
92
|
return response.data.result[1];
|
|
99
93
|
}
|
|
100
94
|
|
|
101
95
|
async connect() {
|
|
96
|
+
const openWrtInfo = { state: false, systemInfo: {}, networkInfo: {}, wirelessStatus: {}, wirelessRadios: [], ssids: [] }
|
|
97
|
+
|
|
102
98
|
try {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
if (this.logDebug) this.emit("debug", `System info data: ${JSON.stringify(systemInfo, null, 2)}`);
|
|
99
|
+
const systemInfo = await this.ubusCall('system', 'board');
|
|
100
|
+
if (this.logDebug) this.emit('debug', `System info data: ${JSON.stringify(systemInfo, null, 2)}`);
|
|
106
101
|
|
|
107
|
-
const
|
|
108
|
-
if (this.logDebug) this.emit(
|
|
102
|
+
const networkInfo = await this.ubusCall('network.device', 'status', { "name": "eth0" });
|
|
103
|
+
if (this.logDebug) this.emit('debug', `Network info data: ${JSON.stringify(networkInfo, null, 2)}`);
|
|
109
104
|
|
|
110
|
-
const
|
|
105
|
+
const wirelessStatus = await this.ubusCall('network.wireless', 'status');
|
|
106
|
+
if (this.logDebug) this.emit('debug', `Wireless status data: ${JSON.stringify(wirelessStatus, null, 2)}`);
|
|
107
|
+
|
|
108
|
+
const wirelessRadios = Object.values(wirelessStatus.radios).map(radio => ({
|
|
111
109
|
name: radio.name,
|
|
112
110
|
state: radio.up === true,
|
|
113
111
|
interfaces: Object.values(radio.interfaces).map(i => ({
|
|
@@ -118,27 +116,29 @@ class OpenWrt extends EventEmitter {
|
|
|
118
116
|
}));
|
|
119
117
|
|
|
120
118
|
const ssids = wirelessRadios.flatMap(radio => radio.interfaces);
|
|
121
|
-
this.emit("systemInfo", systemInfo);
|
|
122
|
-
this.emit("wirelessStatus", wirelessStatus);
|
|
123
|
-
this.emit("wirelessRadios", wirelessRadios);
|
|
124
|
-
this.emit("ssids", ssids);
|
|
125
|
-
|
|
126
|
-
if (this.firstRun) {
|
|
127
|
-
this.emit("success", `Connect success`);
|
|
128
|
-
this.firstRun = false;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
119
|
openWrtInfo.state = true;
|
|
132
120
|
openWrtInfo.systemInfo = systemInfo;
|
|
121
|
+
openWrtInfo.networkInfo = networkInfo;
|
|
133
122
|
openWrtInfo.wirelessStatus = wirelessStatus;
|
|
134
123
|
openWrtInfo.wirelessRadios = wirelessRadios;
|
|
135
124
|
openWrtInfo.ssids = ssids;
|
|
136
125
|
|
|
137
|
-
if (this.
|
|
126
|
+
if (this.firstRun) {
|
|
127
|
+
this.emit('success', `Connect success`);
|
|
128
|
+
this.firstRun = false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// emit data
|
|
132
|
+
this.emit('systemInfo', systemInfo);
|
|
133
|
+
this.emit('networkInfo', networkInfo);
|
|
134
|
+
this.emit('wirelessStatus', wirelessStatus);
|
|
135
|
+
this.emit('wirelessRadios', wirelessRadios);
|
|
136
|
+
this.emit('ssids', ssids);
|
|
137
|
+
|
|
138
138
|
return openWrtInfo;
|
|
139
139
|
} catch (error) {
|
|
140
|
-
if (this.logError) this.emit(
|
|
141
|
-
return
|
|
140
|
+
if (this.logError) this.emit('error', `Connect error: ${error.message}`);
|
|
141
|
+
return openWrtInfo;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -146,29 +146,29 @@ class OpenWrt extends EventEmitter {
|
|
|
146
146
|
switch (type) {
|
|
147
147
|
case 'ssid':
|
|
148
148
|
await this.handleWithLock(async () => {
|
|
149
|
-
if (this.logDebug) this.emit(
|
|
149
|
+
if (this.logDebug) this.emit('debug', `${state ? 'Enabling' : 'Disabling'} SSID ${ssidName}`);
|
|
150
150
|
|
|
151
|
-
const status = await this.ubusCall(
|
|
151
|
+
const status = await this.ubusCall('network.wireless', 'status');
|
|
152
152
|
const iface = await this.functions.findIfaceBySsid(status, ssidName);
|
|
153
153
|
if (!iface) throw new Error(`SSID ${ssidName} not found`);
|
|
154
154
|
|
|
155
155
|
const section = iface.section;
|
|
156
156
|
if (!section) throw new Error(`No UCI section for SSID ${ssidName}`);
|
|
157
157
|
|
|
158
|
-
await this.ubusCall(
|
|
158
|
+
await this.ubusCall('uci', 'set',
|
|
159
159
|
{
|
|
160
|
-
config:
|
|
160
|
+
config: 'wireless',
|
|
161
161
|
section: section,
|
|
162
162
|
values: {
|
|
163
|
-
disabled: state ?
|
|
163
|
+
disabled: state ? '0' : '1'
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
);
|
|
167
167
|
|
|
168
|
-
await this.ubusCall(
|
|
169
|
-
await this.ubusCall(
|
|
168
|
+
await this.ubusCall('uci', 'commit', { config: 'wireless' });
|
|
169
|
+
await this.ubusCall('network.wireless', 'reload', {});
|
|
170
170
|
|
|
171
|
-
if (this.logDebug) this.emit(
|
|
171
|
+
if (this.logDebug) this.emit('debug', `Send SSID ${ssidName} ${state ? 'enabled' : 'disabled'}`);
|
|
172
172
|
});
|
|
173
173
|
break;
|
|
174
174
|
case 'switch':
|
|
@@ -177,5 +177,4 @@ class OpenWrt extends EventEmitter {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
export default OpenWrt;
|
|
181
|
-
|
|
180
|
+
export default OpenWrt;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class Switch extends EventEmitter {
|
|
5
5
|
constructor(api, config, openWrt, openWrtInfo) {
|
|
6
6
|
super();
|
|
7
7
|
|
|
@@ -12,8 +12,9 @@ class SwitchDevice extends EventEmitter {
|
|
|
12
12
|
AccessoryUUID = api.hap.uuid;
|
|
13
13
|
|
|
14
14
|
//config
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
15
|
+
this.host = config.host;
|
|
16
|
+
this.name = config.accessPoint.name || openWrtInfo.systemInfo.hostname;
|
|
17
|
+
this.accessPoint = config.accessPoint;
|
|
17
18
|
this.logInfo = config.log?.info || false;
|
|
18
19
|
this.logDebug = config.log?.debug || false;
|
|
19
20
|
|
|
@@ -65,8 +66,8 @@ class SwitchDevice extends EventEmitter {
|
|
|
65
66
|
this.mqtt1 = new Mqtt({
|
|
66
67
|
host: this.mqtt.host,
|
|
67
68
|
port: this.mqtt.port || 1883,
|
|
68
|
-
clientId: this.mqtt.clientId ? `${this.
|
|
69
|
-
prefix: this.mqtt.prefix ? `${this.
|
|
69
|
+
clientId: this.mqtt.clientId ? `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}_${this.mqtt.clientId}_${Math.random().toString(16).slice(3)}` : `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}_${Math.random().toString(16).slice(3)}`,
|
|
70
|
+
prefix: this.mqtt.prefix ? `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}/${this.mqtt.prefix}/${this.name}` : `${this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt'}/${this.name}`,
|
|
70
71
|
user: this.mqtt.auth?.user,
|
|
71
72
|
passwd: this.mqtt.auth?.passwd,
|
|
72
73
|
logWarn: this.logWarn,
|
|
@@ -121,29 +122,30 @@ class SwitchDevice extends EventEmitter {
|
|
|
121
122
|
//prepare accessory
|
|
122
123
|
if (this.logDebug) this.emit('debug', `prepare accessory`);
|
|
123
124
|
const accessoryName = this.name;
|
|
124
|
-
const accessoryUUID = AccessoryUUID.generate(this.openWrtInfo.systemInfo.
|
|
125
|
-
const accessoryCategory = Categories.
|
|
125
|
+
const accessoryUUID = AccessoryUUID.generate(this.host + this.openWrtInfo.systemInfo.system);
|
|
126
|
+
const accessoryCategory = Categories.AIRPORT;
|
|
126
127
|
const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
|
|
127
128
|
|
|
128
129
|
//prepare information service
|
|
129
130
|
if (this.logDebug) this.emit('debug', `prepare information service`);
|
|
130
131
|
accessory.getService(Service.AccessoryInformation)
|
|
131
|
-
.setCharacteristic(Characteristic.Manufacturer, 'OpenWrt')
|
|
132
|
+
.setCharacteristic(Characteristic.Manufacturer, this.openWrtInfo.systemInfo.release.distribution || 'OpenWrt')
|
|
132
133
|
.setCharacteristic(Characteristic.Model, this.openWrtInfo.systemInfo.model)
|
|
133
134
|
.setCharacteristic(Characteristic.SerialNumber, this.openWrtInfo.systemInfo.system)
|
|
134
|
-
.setCharacteristic(Characteristic.FirmwareRevision, this.openWrtInfo.systemInfo.release?.
|
|
135
|
+
.setCharacteristic(Characteristic.FirmwareRevision, this.openWrtInfo.systemInfo.release?.version)
|
|
135
136
|
.setCharacteristic(Characteristic.ConfiguredName, accessoryName);
|
|
136
137
|
|
|
137
138
|
if (this.logDebug) this.emit('debug', `prepare service`);
|
|
138
139
|
|
|
139
|
-
//
|
|
140
|
+
//services
|
|
140
141
|
this.services = [];
|
|
142
|
+
this.sensorServices = [];
|
|
141
143
|
for (const port of this.ports) {
|
|
142
144
|
const name = port.name;
|
|
143
145
|
if (this.logDebug) this.emit('debug', `prepare port: ${name} service`);
|
|
144
146
|
|
|
145
|
-
const serviceName = this.accessPoint.namePrefix ? `${accessoryName} ${
|
|
146
|
-
const service = accessory.addService(Service.Switch, serviceName, `service${
|
|
147
|
+
const serviceName = this.accessPoint.namePrefix ? `${accessoryName} ${name}` : name;
|
|
148
|
+
const service = accessory.addService(Service.Switch, serviceName, `service${name}`);
|
|
147
149
|
service.addOptionalCharacteristic(Characteristic.ConfiguredName);
|
|
148
150
|
service.setCharacteristic(Characteristic.ConfiguredName, serviceName);
|
|
149
151
|
service.getCharacteristic(Characteristic.On)
|
|
@@ -166,7 +168,6 @@ class SwitchDevice extends EventEmitter {
|
|
|
166
168
|
if (this.accessPoint.sensor) {
|
|
167
169
|
if (this.logDebug) this.emit('debug', `prepare port: ${name} sensor service`);
|
|
168
170
|
|
|
169
|
-
this.sensorServices = [];
|
|
170
171
|
const sensorService = accessory.addService(Service.ContactSensor, serviceName, `sensorService${name}`);
|
|
171
172
|
sensorService.addOptionalCharacteristic(Characteristic.ConfiguredName);
|
|
172
173
|
sensorService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
|
|
@@ -191,39 +192,46 @@ class SwitchDevice extends EventEmitter {
|
|
|
191
192
|
//start external integrations
|
|
192
193
|
if (this.restFul.enable || this.mqtt.enable) await this.externalIntegrations();
|
|
193
194
|
|
|
194
|
-
this.emit('devInfo', `--------
|
|
195
|
-
this.emit('devInfo', `
|
|
196
|
-
this.emit('devInfo', `Model: ${this.openWrtInfo.systemInfo.model}`);
|
|
195
|
+
this.emit('devInfo', `-------- Access Point ${this.name} --------`);
|
|
196
|
+
this.emit('devInfo', `Model: ${this.openWrtInfo.systemInfo.model || this.openWrtInfo.systemInfo.board_name}`);
|
|
197
197
|
this.emit('devInfo', `System: ${this.openWrtInfo.systemInfo.system}`);
|
|
198
|
+
this.emit('devInfo', `Kernel: ${this.openWrtInfo.systemInfo.kernel}`);
|
|
198
199
|
this.emit('devInfo', `Firmware: ${this.openWrtInfo.systemInfo.release?.description}`);
|
|
200
|
+
this.emit('devInfo', `Target: ${this.openWrtInfo.systemInfo.release?.target}`);
|
|
201
|
+
this.emit('devInfo', `Ports: ${this.ports.length}`);
|
|
199
202
|
this.emit('devInfo', `----------------------------------`);
|
|
200
203
|
|
|
201
204
|
//openwrt client
|
|
202
205
|
this.openWrt.on('systemInfo', (info) => {
|
|
203
|
-
this.informationService?.updateCharacteristic(Characteristic.FirmwareRevision, info.release?.
|
|
206
|
+
this.informationService?.updateCharacteristic(Characteristic.FirmwareRevision, info.release?.version);
|
|
204
207
|
})
|
|
205
|
-
.on('
|
|
208
|
+
.on('networkInfo', async (info) => {
|
|
206
209
|
})
|
|
207
|
-
.on('
|
|
210
|
+
.on('wirelessStatus', async (status) => {
|
|
211
|
+
})
|
|
212
|
+
.on('wirelessRadios', async (radios) => {
|
|
213
|
+
})
|
|
214
|
+
.on('ports', async (ports) => {
|
|
215
|
+
this.ports = ports;
|
|
216
|
+
|
|
208
217
|
// sensors
|
|
209
218
|
for (let i = 0; i < ports.length; i++) {
|
|
210
219
|
const port = ports[i];
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
const state = port[i].state;
|
|
220
|
+
const name = port.name;
|
|
221
|
+
const state = port.state;
|
|
214
222
|
const serviceName = this.accessPoint.namePrefix ? `${this.name} ${name}` : name;
|
|
215
223
|
this.services?.[i]
|
|
216
224
|
?.setCharacteristic(Characteristic.ConfiguredName, serviceName)
|
|
217
225
|
.updateCharacteristic(Characteristic.On, state);
|
|
218
226
|
|
|
219
227
|
this.sensorServices?.[i]
|
|
220
|
-
?.setCharacteristic(Characteristic.ConfiguredName,
|
|
221
|
-
.updateCharacteristic(Characteristic.ContactSensorState, state
|
|
228
|
+
?.setCharacteristic(Characteristic.ConfiguredName, serviceName)
|
|
229
|
+
.updateCharacteristic(Characteristic.ContactSensorState, !state);
|
|
222
230
|
|
|
223
231
|
if (this.logInfo) {
|
|
224
|
-
this.emit('info', `
|
|
225
|
-
this.emit('info', `
|
|
226
|
-
this.emit('info', `Mode: ${
|
|
232
|
+
this.emit('info', `Name: ${ports.name}`);
|
|
233
|
+
this.emit('info', `State: ${ports.state}`);
|
|
234
|
+
this.emit('info', `Mode: ${ports.mode}`);
|
|
227
235
|
}
|
|
228
236
|
}
|
|
229
237
|
})
|
|
@@ -242,4 +250,4 @@ class SwitchDevice extends EventEmitter {
|
|
|
242
250
|
}
|
|
243
251
|
}
|
|
244
252
|
};
|
|
245
|
-
export default
|
|
253
|
+
export default Switch;
|