homebridge-openwrt-control 0.0.2-beta.10 → 0.0.2-beta.12
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 +1 -1
- package/package.json +1 -1
- package/src/openwrt.js +93 -56
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",
|
package/package.json
CHANGED
package/src/openwrt.js
CHANGED
|
@@ -1,76 +1,111 @@
|
|
|
1
|
-
import EventEmitter from
|
|
2
|
-
import
|
|
3
|
-
import Functions from
|
|
4
|
-
import ImpulseGenerator from
|
|
1
|
+
import EventEmitter from 'events';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import Functions from './functions.js';
|
|
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.passwd = config.auth?.passwd || "";
|
|
13
|
-
|
|
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
|
|
|
15
|
+
//external integration
|
|
16
|
+
this.restFulEnabled = config.restFul?.enable || false;
|
|
17
|
+
this.mqttEnabled = config.mqtt?.enable || false;
|
|
18
|
+
|
|
17
19
|
this.firstRun = true;
|
|
18
20
|
this.lock = false;
|
|
19
21
|
|
|
22
|
+
this.sessionId = null;
|
|
23
|
+
this.sessionExpiresAt = 0;
|
|
24
|
+
|
|
20
25
|
this.functions = new Functions();
|
|
26
|
+
this.axiosInstance = axios.create({
|
|
27
|
+
baseURL: `http://${config.host}/ubus`,
|
|
28
|
+
timeout: 5000,
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json",
|
|
31
|
+
"Accept": "application/json"
|
|
32
|
+
}
|
|
33
|
+
});
|
|
21
34
|
|
|
22
35
|
this.impulseGenerator = new ImpulseGenerator()
|
|
23
|
-
.on(
|
|
36
|
+
.on('connect', () => this.handleWithLock(async () => {
|
|
24
37
|
await this.connect();
|
|
25
38
|
}))
|
|
26
|
-
.on(
|
|
27
|
-
this.emit(state ?
|
|
39
|
+
.on('state', (state) => {
|
|
40
|
+
this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
|
|
28
41
|
});
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
async handleWithLock(fn) {
|
|
32
45
|
if (this.lock) return;
|
|
33
46
|
this.lock = true;
|
|
47
|
+
|
|
34
48
|
try {
|
|
35
49
|
await fn();
|
|
36
50
|
} catch (error) {
|
|
37
|
-
this.emit(
|
|
51
|
+
this.emit('error', `Impulse generator error: ${error.message}`
|
|
52
|
+
);
|
|
38
53
|
} finally {
|
|
39
54
|
this.lock = false;
|
|
40
55
|
}
|
|
41
56
|
}
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
});
|
|
58
|
+
async login() {
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
if (this.sessionId && now < this.sessionExpiresAt) {
|
|
61
|
+
return this.sessionId;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const response = await this.axiosInstance.post('', {
|
|
65
|
+
jsonrpc: '2.0',
|
|
66
|
+
id: 1,
|
|
67
|
+
method: 'call',
|
|
68
|
+
params: ['00000000000000000000000000000000', 'session', 'login', { username: this.user, password: this.passwd }]
|
|
56
69
|
});
|
|
70
|
+
|
|
71
|
+
const result = response.data?.result?.[1];
|
|
72
|
+
if (!result?.ubus_rpc_session) {
|
|
73
|
+
throw new Error('ubus login failed');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
this.sessionId = result.ubus_rpc_session;
|
|
77
|
+
this.sessionExpiresAt = now + 240_000;
|
|
78
|
+
|
|
79
|
+
if (this.logDebug) this.emit('debug', `Ubus login OK`);
|
|
80
|
+
return this.sessionId;
|
|
57
81
|
}
|
|
58
82
|
|
|
59
|
-
// --- ubus call przez SSH ---
|
|
60
83
|
async ubusCall(service, method, params = {}) {
|
|
61
|
-
const
|
|
62
|
-
|
|
84
|
+
const session = await this.login();
|
|
85
|
+
|
|
86
|
+
const response = await this.axiosInstance.post('', {
|
|
87
|
+
jsonrpc: '2.0',
|
|
88
|
+
id: 2,
|
|
89
|
+
method: 'call',
|
|
90
|
+
params: [session, service, method, params]
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (response.data?.error) {
|
|
94
|
+
throw new Error(response.data.error.message || 'ubus call error');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return response.data.result[1];
|
|
63
98
|
}
|
|
64
99
|
|
|
65
|
-
// --- Pobranie info i statusu ---
|
|
66
100
|
async connect() {
|
|
67
|
-
const openWrtInfo = { state: false, systemInfo: {}, wirelessStatus: {}, wirelessRadios: [], ssids: [] }
|
|
101
|
+
const openWrtInfo = { state: false, systemInfo: {}, wirelessStatus: {}, wirelessRadios: [], ssids: [] }
|
|
102
|
+
|
|
68
103
|
try {
|
|
69
|
-
const systemInfo = await this.ubusCall(
|
|
70
|
-
if (this.logDebug) this.emit(
|
|
104
|
+
const systemInfo = await this.ubusCall('system', 'board');
|
|
105
|
+
if (this.logDebug) this.emit('debug', `System info data: ${JSON.stringify(systemInfo, null, 2)}`);
|
|
71
106
|
|
|
72
|
-
const wirelessStatus = await this.ubusCall(
|
|
73
|
-
if (this.logDebug) this.emit(
|
|
107
|
+
const wirelessStatus = await this.ubusCall('network.wireless', 'status');
|
|
108
|
+
if (this.logDebug) this.emit('debug', `Wireless status data: ${JSON.stringify(wirelessStatus, null, 2)}`);
|
|
74
109
|
|
|
75
110
|
const wirelessRadios = Object.values(wirelessStatus.radios).map(radio => ({
|
|
76
111
|
name: radio.name,
|
|
@@ -83,14 +118,13 @@ class OpenWrt extends EventEmitter {
|
|
|
83
118
|
}));
|
|
84
119
|
|
|
85
120
|
const ssids = wirelessRadios.flatMap(radio => radio.interfaces);
|
|
86
|
-
|
|
87
|
-
this.emit(
|
|
88
|
-
this.emit(
|
|
89
|
-
this.emit(
|
|
90
|
-
this.emit("ssids", ssids);
|
|
121
|
+
this.emit('systemInfo', systemInfo);
|
|
122
|
+
this.emit('wirelessStatus', wirelessStatus);
|
|
123
|
+
this.emit('wirelessRadios', wirelessRadios);
|
|
124
|
+
this.emit('ssids', ssids);
|
|
91
125
|
|
|
92
126
|
if (this.firstRun) {
|
|
93
|
-
this.emit(
|
|
127
|
+
this.emit('success', `Connect success`);
|
|
94
128
|
this.firstRun = false;
|
|
95
129
|
}
|
|
96
130
|
|
|
@@ -100,40 +134,44 @@ class OpenWrt extends EventEmitter {
|
|
|
100
134
|
openWrtInfo.wirelessRadios = wirelessRadios;
|
|
101
135
|
openWrtInfo.ssids = ssids;
|
|
102
136
|
|
|
103
|
-
if (this.logDebug) this.emit(
|
|
137
|
+
if (this.logDebug) this.emit('debug', `OpenWrt Data: ${JSON.stringify(openWrtInfo, null, 2)}`);
|
|
104
138
|
return openWrtInfo;
|
|
105
139
|
} catch (error) {
|
|
106
|
-
if (this.logError) this.emit(
|
|
140
|
+
if (this.logError) this.emit('error', `Connect error: ${error.message}`);
|
|
107
141
|
return openWrtInfo;
|
|
108
142
|
}
|
|
109
143
|
}
|
|
110
144
|
|
|
111
|
-
// --- Włączanie / wyłączanie SSID ---
|
|
112
145
|
async send(type, ssidName, state) {
|
|
113
146
|
switch (type) {
|
|
114
|
-
case
|
|
147
|
+
case 'ssid':
|
|
115
148
|
await this.handleWithLock(async () => {
|
|
116
|
-
if (this.logDebug) this.emit(
|
|
149
|
+
if (this.logDebug) this.emit('debug', `${state ? 'Enabling' : 'Disabling'} SSID ${ssidName}`);
|
|
117
150
|
|
|
118
|
-
const status = await this.ubusCall(
|
|
151
|
+
const status = await this.ubusCall('network.wireless', 'status');
|
|
119
152
|
const iface = await this.functions.findIfaceBySsid(status, ssidName);
|
|
120
153
|
if (!iface) throw new Error(`SSID ${ssidName} not found`);
|
|
121
154
|
|
|
122
155
|
const section = iface.section;
|
|
123
156
|
if (!section) throw new Error(`No UCI section for SSID ${ssidName}`);
|
|
124
157
|
|
|
125
|
-
await this.ubusCall(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
158
|
+
await this.ubusCall('uci', 'set',
|
|
159
|
+
{
|
|
160
|
+
config: 'wireless',
|
|
161
|
+
section: section,
|
|
162
|
+
values: {
|
|
163
|
+
disabled: state ? '0' : '1'
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
);
|
|
132
167
|
|
|
133
|
-
|
|
168
|
+
await this.ubusCall('uci', 'commit', { config: 'wireless' });
|
|
169
|
+
await this.ubusCall('network.wireless', 'reload', {});
|
|
170
|
+
|
|
171
|
+
if (this.logDebug) this.emit('debug', `Send SSID ${ssidName} ${state ? 'enabled' : 'disabled'}`);
|
|
134
172
|
});
|
|
135
173
|
break;
|
|
136
|
-
case
|
|
174
|
+
case 'switch':
|
|
137
175
|
break;
|
|
138
176
|
}
|
|
139
177
|
}
|
|
@@ -141,4 +179,3 @@ class OpenWrt extends EventEmitter {
|
|
|
141
179
|
|
|
142
180
|
export default OpenWrt;
|
|
143
181
|
|
|
144
|
-
|