homebridge-openwrt-control 0.0.1-beta.0
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 +436 -0
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/config.schema.json +463 -0
- package/index.js +143 -0
- package/package.json +53 -0
- package/src/apdevice.js +247 -0
- package/src/constants.js +6 -0
- package/src/functions.js +81 -0
- package/src/impulsegenerator.js +41 -0
- package/src/openwrt.js +173 -0
- package/src/swdevice.js +247 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "OpenWrt",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"singular": true,
|
|
5
|
+
"fixArrays": true,
|
|
6
|
+
"strictValidation": true,
|
|
7
|
+
"headerDisplay": "This plugin works with OpenWrt Devices based on Dashboard API. Devices are exposed to HomeKit as separate accessories and each needs to be manually paired.",
|
|
8
|
+
"footerDisplay": "For documentation please see [GitHub repository](https://github.com/grzegorz914/homebridge-openwrt-control).",
|
|
9
|
+
"schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"devices": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"title": "Network",
|
|
17
|
+
"properties": {
|
|
18
|
+
"name": {
|
|
19
|
+
"title": "Name",
|
|
20
|
+
"type": "string",
|
|
21
|
+
"placeholder": "OpenWrt"
|
|
22
|
+
},
|
|
23
|
+
"host": {
|
|
24
|
+
"title": "IP/Hostname",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"placeholder": "192.168.1.10 or openwrt.local",
|
|
27
|
+
"pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(\\.([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?))*)$"
|
|
28
|
+
},
|
|
29
|
+
"auth": {
|
|
30
|
+
"title": "Authorization",
|
|
31
|
+
"type": "object",
|
|
32
|
+
"properties": {
|
|
33
|
+
"enable": {
|
|
34
|
+
"title": "Enable",
|
|
35
|
+
"type": "boolean",
|
|
36
|
+
"default": false
|
|
37
|
+
},
|
|
38
|
+
"user": {
|
|
39
|
+
"title": "User",
|
|
40
|
+
"type": "string",
|
|
41
|
+
"placeholder": "User",
|
|
42
|
+
"condition": {
|
|
43
|
+
"functionBody": "return model.devices[arrayIndices].auth.enable === true;"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"passwd": {
|
|
47
|
+
"title": "Password",
|
|
48
|
+
"type": "string",
|
|
49
|
+
"placeholder": "Password",
|
|
50
|
+
"format": "password",
|
|
51
|
+
"condition": {
|
|
52
|
+
"functionBody": "return model.devices[arrayIndices].auth.enable === true;"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"allOf": [
|
|
57
|
+
{
|
|
58
|
+
"if": {
|
|
59
|
+
"required": [
|
|
60
|
+
"enable"
|
|
61
|
+
],
|
|
62
|
+
"properties": {
|
|
63
|
+
"enable": {
|
|
64
|
+
"const": true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"then": {
|
|
69
|
+
"required": [
|
|
70
|
+
"user",
|
|
71
|
+
"passwd"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"displayType": {
|
|
78
|
+
"title": "Accessory",
|
|
79
|
+
"type": "integer",
|
|
80
|
+
"minimum": 0,
|
|
81
|
+
"maximum": 1,
|
|
82
|
+
"default": 0,
|
|
83
|
+
"description": "Accessory type for Home app",
|
|
84
|
+
"anyOf": [
|
|
85
|
+
{
|
|
86
|
+
"title": "Disabled",
|
|
87
|
+
"enum": [
|
|
88
|
+
0
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"title": "Enabled",
|
|
93
|
+
"enum": [
|
|
94
|
+
1
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"accessPoint": {
|
|
100
|
+
"title": "Access point",
|
|
101
|
+
"type": "object",
|
|
102
|
+
"properties": {
|
|
103
|
+
"enable": {
|
|
104
|
+
"title": "Enable",
|
|
105
|
+
"type": "boolean",
|
|
106
|
+
"description": "Here Enable/Disable this access point control."
|
|
107
|
+
},
|
|
108
|
+
"name": {
|
|
109
|
+
"title": "Name",
|
|
110
|
+
"type": "string",
|
|
111
|
+
"placeholder": "Name",
|
|
112
|
+
"description": "Here set the Name to be displayed in Homebridge/HomeKit for this access point.",
|
|
113
|
+
"condition": {
|
|
114
|
+
"functionBody": "return model.devices[arrayIndices[0]].accessPoint.enable === true;"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"namePrefix": {
|
|
118
|
+
"title": "Prefix",
|
|
119
|
+
"type": "boolean",
|
|
120
|
+
"description": "Here enable/disable the accessory name as a prefix for the access point name.",
|
|
121
|
+
"condition": {
|
|
122
|
+
"functionBody": "return model.devices[arrayIndices[0]].accessPoint.enable === true;"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"sensor": {
|
|
126
|
+
"title": "Enable",
|
|
127
|
+
"type": "boolean",
|
|
128
|
+
"description": "Here Enable/Disable sensor for every ssid.",
|
|
129
|
+
"condition": {
|
|
130
|
+
"functionBody": "return model.devices[arrayIndices].accessPoint.enable === true;"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"refreshInterval": {
|
|
136
|
+
"title": "Refresh Interval (sec)",
|
|
137
|
+
"type": "integer",
|
|
138
|
+
"minimum": 0,
|
|
139
|
+
"maximum": 60,
|
|
140
|
+
"default": 5,
|
|
141
|
+
"description": "Here set the data refresh time in (sec)."
|
|
142
|
+
},
|
|
143
|
+
"log": {
|
|
144
|
+
"title": "Log",
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"deviceInfo": {
|
|
148
|
+
"title": "Device Info",
|
|
149
|
+
"type": "boolean",
|
|
150
|
+
"default": true,
|
|
151
|
+
"description": "This enable logging device info by every connections device to the network."
|
|
152
|
+
},
|
|
153
|
+
"success": {
|
|
154
|
+
"title": "Success",
|
|
155
|
+
"type": "boolean",
|
|
156
|
+
"default": true
|
|
157
|
+
},
|
|
158
|
+
"info": {
|
|
159
|
+
"title": "Info",
|
|
160
|
+
"type": "boolean",
|
|
161
|
+
"default": false
|
|
162
|
+
},
|
|
163
|
+
"warn": {
|
|
164
|
+
"title": "Warn",
|
|
165
|
+
"type": "boolean",
|
|
166
|
+
"default": true
|
|
167
|
+
},
|
|
168
|
+
"error": {
|
|
169
|
+
"title": "Error",
|
|
170
|
+
"type": "boolean",
|
|
171
|
+
"default": true
|
|
172
|
+
},
|
|
173
|
+
"debug": {
|
|
174
|
+
"title": "Debug",
|
|
175
|
+
"type": "boolean",
|
|
176
|
+
"default": false
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"restFul": {
|
|
181
|
+
"title": "RESTFul",
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"enable": {
|
|
185
|
+
"title": "Enable",
|
|
186
|
+
"type": "boolean",
|
|
187
|
+
"default": false,
|
|
188
|
+
"description": "This enable RESTful server."
|
|
189
|
+
},
|
|
190
|
+
"port": {
|
|
191
|
+
"title": "Port",
|
|
192
|
+
"type": "integer",
|
|
193
|
+
"placeholder": 3000,
|
|
194
|
+
"description": "Here set the listening Port for RESTful server.",
|
|
195
|
+
"condition": {
|
|
196
|
+
"functionBody": "return model.devices[arrayIndices].restFul.enable == true;"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"mqtt": {
|
|
202
|
+
"title": "MQTT",
|
|
203
|
+
"type": "object",
|
|
204
|
+
"properties": {
|
|
205
|
+
"enable": {
|
|
206
|
+
"title": "Enable",
|
|
207
|
+
"type": "boolean",
|
|
208
|
+
"default": false,
|
|
209
|
+
"description": "This enable MQTT client."
|
|
210
|
+
},
|
|
211
|
+
"host": {
|
|
212
|
+
"title": "IP/Hostname",
|
|
213
|
+
"type": "string",
|
|
214
|
+
"placeholder": "192.168.1.20 or mqtt.local",
|
|
215
|
+
"pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(\\.([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?))*)$",
|
|
216
|
+
"description": "Here set the IP/Hostname of MQTT Broker.",
|
|
217
|
+
"condition": {
|
|
218
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.enable == true;"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
"port": {
|
|
222
|
+
"title": "Port",
|
|
223
|
+
"type": "integer",
|
|
224
|
+
"placeholder": 1883,
|
|
225
|
+
"description": "Here set the port of MQTT Broker.",
|
|
226
|
+
"condition": {
|
|
227
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.enable == true;"
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
"clientId": {
|
|
231
|
+
"title": "Client ID",
|
|
232
|
+
"type": "string",
|
|
233
|
+
"placeholder": "client id",
|
|
234
|
+
"description": "Here optional set the Client ID of MQTT Broker.",
|
|
235
|
+
"condition": {
|
|
236
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.enable == true;"
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"prefix": {
|
|
240
|
+
"title": "Prefix",
|
|
241
|
+
"type": "string",
|
|
242
|
+
"placeholder": "home",
|
|
243
|
+
"description": "Here set the prefix.",
|
|
244
|
+
"condition": {
|
|
245
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.enable == true;"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"auth": {
|
|
249
|
+
"title": "Authorization",
|
|
250
|
+
"type": "object",
|
|
251
|
+
"properties": {
|
|
252
|
+
"enable": {
|
|
253
|
+
"title": "Enable",
|
|
254
|
+
"type": "boolean",
|
|
255
|
+
"description": "This enable authorization for MQTT Broker."
|
|
256
|
+
},
|
|
257
|
+
"user": {
|
|
258
|
+
"title": "User",
|
|
259
|
+
"type": "string",
|
|
260
|
+
"placeholder": "user",
|
|
261
|
+
"description": "Here set the user of MQTT Broker.",
|
|
262
|
+
"condition": {
|
|
263
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.auth.enable === true;"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"passwd": {
|
|
267
|
+
"title": "Password",
|
|
268
|
+
"type": "string",
|
|
269
|
+
"placeholder": "password",
|
|
270
|
+
"description": "Here set the password of MQTT Broker.",
|
|
271
|
+
"format": "password",
|
|
272
|
+
"condition": {
|
|
273
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.auth.enable === true;"
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
"condition": {
|
|
278
|
+
"functionBody": "return model.devices[arrayIndices].mqtt.enable == true;"
|
|
279
|
+
},
|
|
280
|
+
"allOf": [
|
|
281
|
+
{
|
|
282
|
+
"if": {
|
|
283
|
+
"required": [
|
|
284
|
+
"enable"
|
|
285
|
+
],
|
|
286
|
+
"properties": {
|
|
287
|
+
"enable": {
|
|
288
|
+
"const": true
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
"then": {
|
|
293
|
+
"required": [
|
|
294
|
+
"user",
|
|
295
|
+
"passwd"
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
"allOf": [
|
|
303
|
+
{
|
|
304
|
+
"if": {
|
|
305
|
+
"required": [
|
|
306
|
+
"enable"
|
|
307
|
+
],
|
|
308
|
+
"properties": {
|
|
309
|
+
"enable": {
|
|
310
|
+
"const": true
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
"then": {
|
|
315
|
+
"required": [
|
|
316
|
+
"host"
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
"required": [
|
|
324
|
+
"name",
|
|
325
|
+
"host",
|
|
326
|
+
"displayType"
|
|
327
|
+
],
|
|
328
|
+
"allOf": [
|
|
329
|
+
{
|
|
330
|
+
"if": {
|
|
331
|
+
"properties": {
|
|
332
|
+
"displayType": {
|
|
333
|
+
"enum": [
|
|
334
|
+
1
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
"then": {
|
|
340
|
+
"required": [
|
|
341
|
+
"host"
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
"layout": [
|
|
351
|
+
{
|
|
352
|
+
"key": "devices",
|
|
353
|
+
"type": "tabarray",
|
|
354
|
+
"title": "{{ value.name || 'Device' }}",
|
|
355
|
+
"items": [
|
|
356
|
+
"devices[].name",
|
|
357
|
+
"devices[].host",
|
|
358
|
+
"devices[].displayType",
|
|
359
|
+
{
|
|
360
|
+
"key": "devices[]",
|
|
361
|
+
"type": "section",
|
|
362
|
+
"title": "Advanced Settings",
|
|
363
|
+
"expandable": true,
|
|
364
|
+
"expanded": false,
|
|
365
|
+
"items": [
|
|
366
|
+
{
|
|
367
|
+
"key": "devices[]",
|
|
368
|
+
"type": "tabarray",
|
|
369
|
+
"title": "{{ value.title }}",
|
|
370
|
+
"items": [
|
|
371
|
+
{
|
|
372
|
+
"key": "devices[].accessPoint",
|
|
373
|
+
"title": "Access Point",
|
|
374
|
+
"items": [
|
|
375
|
+
"devices[].accessPoint.enable",
|
|
376
|
+
"devices[].accessPoint.name",
|
|
377
|
+
"devices[].accessPoint.namePrefix",
|
|
378
|
+
"devices[].accessPoint.sensors"
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"key": "devices[].auth",
|
|
383
|
+
"title": "Authorization",
|
|
384
|
+
"items": [
|
|
385
|
+
"devices[].auth.enable",
|
|
386
|
+
"devices[].auth.user",
|
|
387
|
+
{
|
|
388
|
+
"key": "devices[].auth.passwd",
|
|
389
|
+
"type": "password"
|
|
390
|
+
}
|
|
391
|
+
]
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"key": "devices[]",
|
|
395
|
+
"title": "Devices",
|
|
396
|
+
"items": [
|
|
397
|
+
"devices[].refreshInterval"
|
|
398
|
+
]
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"key": "devices[].log",
|
|
402
|
+
"title": "Log",
|
|
403
|
+
"items": [
|
|
404
|
+
"devices[].log.deviceInfo",
|
|
405
|
+
"devices[].log.success",
|
|
406
|
+
"devices[].log.info",
|
|
407
|
+
"devices[].log.warn",
|
|
408
|
+
"devices[].log.error",
|
|
409
|
+
"devices[].log.debug"
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"key": "devices[]",
|
|
414
|
+
"title": "External Integrations",
|
|
415
|
+
"items": [
|
|
416
|
+
{
|
|
417
|
+
"key": "devices[]",
|
|
418
|
+
"type": "tabarray",
|
|
419
|
+
"title": "{{ value.title }}",
|
|
420
|
+
"items": [
|
|
421
|
+
{
|
|
422
|
+
"key": "devices[].restFul",
|
|
423
|
+
"title": "RESTFul",
|
|
424
|
+
"items": [
|
|
425
|
+
"devices[].restFul.enable",
|
|
426
|
+
"devices[].restFul.port"
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
"key": "devices[].mqtt",
|
|
431
|
+
"title": "MQTT",
|
|
432
|
+
"items": [
|
|
433
|
+
"devices[].mqtt.enable",
|
|
434
|
+
"devices[].mqtt.host",
|
|
435
|
+
"devices[].mqtt.port",
|
|
436
|
+
"devices[].mqtt.clientId",
|
|
437
|
+
"devices[].mqtt.prefix",
|
|
438
|
+
{
|
|
439
|
+
"key": "devices[].mqtt.auth",
|
|
440
|
+
"title": "Authorization",
|
|
441
|
+
"items": [
|
|
442
|
+
"devices[].mqtt.auth.enable",
|
|
443
|
+
"devices[].mqtt.auth.user",
|
|
444
|
+
{
|
|
445
|
+
"key": "devices[].mqtt.auth.passwd",
|
|
446
|
+
"type": "password"
|
|
447
|
+
}
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
]
|
|
451
|
+
}
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
]
|
|
455
|
+
}
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
]
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
]
|
|
463
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
3
|
+
import AccessPointDevice from './src/apdevice.js';
|
|
4
|
+
import OpenWrt from './src/openwrt.js';
|
|
5
|
+
import ImpulseGenerator from './src/impulsegenerator.js';
|
|
6
|
+
import { PluginName, PlatformName } from './src/constants.js';
|
|
7
|
+
|
|
8
|
+
class OpenWrtPlatform {
|
|
9
|
+
constructor(log, config, api) {
|
|
10
|
+
// only load if configured
|
|
11
|
+
if (!config || !Array.isArray(config.devices)) {
|
|
12
|
+
log.warn(`No configuration found for ${PluginName}`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
this.accessories = [];
|
|
16
|
+
this.devices = [];
|
|
17
|
+
|
|
18
|
+
//check if prefs directory exist
|
|
19
|
+
const prefDir = join(api.user.storagePath(), 'openWrt');
|
|
20
|
+
try {
|
|
21
|
+
mkdirSync(prefDir, { recursive: true });
|
|
22
|
+
} catch (error) {
|
|
23
|
+
log.error(`Prepare directory error: ${error.message ?? error}`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
api.on('didFinishLaunching', async () => {
|
|
28
|
+
for (const config of config.devices) {
|
|
29
|
+
const { name, host, port, displayType } = config;
|
|
30
|
+
if (!name || !host || !port || !displayType) {
|
|
31
|
+
log.warn(`Device: ${host || 'host missing'}, ${name || 'name missing'}, ${port || 'port missing'}${!displayType ? ', disply type disabled' : ''} in config, will not be published in the Home app`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//log config
|
|
36
|
+
const logLevel = {
|
|
37
|
+
devInfo: config.log?.deviceInfo,
|
|
38
|
+
success: config.log?.success,
|
|
39
|
+
info: config.log?.info,
|
|
40
|
+
warn: config.log?.warn,
|
|
41
|
+
error: config.log?.error,
|
|
42
|
+
debug: config.log?.debug
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
if (logLevel.debug) {
|
|
46
|
+
log.info(`Device: ${host} ${name}, did finish launching.`);
|
|
47
|
+
const safeConfig = {
|
|
48
|
+
...config,
|
|
49
|
+
auth: {
|
|
50
|
+
...config.auth,
|
|
51
|
+
passwd: 'removed',
|
|
52
|
+
},
|
|
53
|
+
mqtt: {
|
|
54
|
+
auth: {
|
|
55
|
+
...config.mqtt?.auth,
|
|
56
|
+
passwd: 'removed',
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
log.info(`Device: ${host} ${name}, Config: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const refreshInterval = (config.refreshInterval ?? 5) * 1000;
|
|
64
|
+
if (config.accessPoint?.enable) this.devices.push('accessPoint');
|
|
65
|
+
if (config.switch?.enable) this.devices.push('switch');
|
|
66
|
+
|
|
67
|
+
if (this.devices.length === 0) return;
|
|
68
|
+
|
|
69
|
+
const openWrt = new OpenWrt(config)
|
|
70
|
+
.on('success', msg => logLevel.success && log.success(`Device: ${host}, ${msg}`))
|
|
71
|
+
.on('info', msg => log.info(`Device: ${host}, ${msg}`))
|
|
72
|
+
.on('debug', msg => log.info(`Device: ${host}, debug: ${msg}`))
|
|
73
|
+
.on('warn', msg => log.warn(`Device: ${host}, ${msg}`))
|
|
74
|
+
.on('error', msg => log.error(`Device: ${host}, ${msg}`))
|
|
75
|
+
|
|
76
|
+
const openWrtInfo = await openWrt.connect();
|
|
77
|
+
if (!openWrtInfo.state) {
|
|
78
|
+
if (logLevel.warn) log.warn(`Device: ${host} ${name}, no data received`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
for (const device of this.devices) {
|
|
84
|
+
// create impulse generator
|
|
85
|
+
const impulseGenerator = new ImpulseGenerator()
|
|
86
|
+
.on('start', async () => {
|
|
87
|
+
try {
|
|
88
|
+
|
|
89
|
+
// create device instance
|
|
90
|
+
let type;
|
|
91
|
+
switch (device) {
|
|
92
|
+
case 'accessPoint': type = new AccessPointDevice(api, config, openWrt, openWrtInfo); break;
|
|
93
|
+
case 'switch': type = new SwitchDevice(api, config, device.switch, openWrt, openWrtInfo); break;
|
|
94
|
+
default:
|
|
95
|
+
if (logLevel.warn) log.warn(`Device: ${host} ${name}, unknown zone: ${zoneControl}`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
type
|
|
100
|
+
.on('devInfo', msg => logLevel.devInfo && log.info(msg))
|
|
101
|
+
.on('success', msg => logLevel.success && log.success(`Device: ${host} ${name}, ${msg}`))
|
|
102
|
+
.on('info', msg => log.info(`Device: ${host} ${name}, ${msg}`))
|
|
103
|
+
.on('debug', msg => log.info(`Device: ${host} ${name}, debug: ${msg}`))
|
|
104
|
+
.on('warn', msg => log.warn(`Device: ${host} ${name}, ${msg}`))
|
|
105
|
+
.on('error', msg => log.error(`Device: ${host} ${name}, ${msg}`));
|
|
106
|
+
|
|
107
|
+
const accessory = await type.start();
|
|
108
|
+
if (accessory) {
|
|
109
|
+
api.publishExternalAccessories(PluginName, [accessory]);
|
|
110
|
+
if (logLevel.success) log.success(`Device: ${host} ${name}, Published as external accessory.`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// stop master impulse generator
|
|
114
|
+
await impulseGenerator.state(false);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (logLevel.error) log.error(`Device: ${host} ${name}, Start impulse generator error: ${error.message ?? error}, trying again.`);
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
.on('state', (state) => {
|
|
120
|
+
if (logLevel.debug) log.info(`Device: ${host} ${name}, Start impulse generator ${state ? 'started' : 'stopped'}.`);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// start impulse generator
|
|
124
|
+
await impulseGenerator.state(true, [{ name: 'start', sampling: 120000 }]);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// start openwrt impulse generator
|
|
128
|
+
await openWrt.impulseGenerator.state(true, [{ name: 'connect', sampling: refreshInterval }], false);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (logLevel.error) log.error(`Device: ${host} ${name}, Did finish launching error: ${error.message ?? error}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
configureAccessory(accessory) {
|
|
137
|
+
this.accessories.push(accessory);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export default (api) => {
|
|
142
|
+
api.registerPlatform(PluginName, PlatformName, OpenWrtPlatform);
|
|
143
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"displayName": "OpenWrt Control",
|
|
3
|
+
"name": "homebridge-openwrt-control",
|
|
4
|
+
"version": "0.0.1-beta.0",
|
|
5
|
+
"description": "Homebridge plugin to control OpenWrt flashed devices.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "grzegorz914",
|
|
8
|
+
"maintainers": [
|
|
9
|
+
"grzegorz914"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/grzegorz914/homebridge-openwrt-control#readme",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/grzegorz914/homebridge-openwrt-control.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/grzegorz914/homebridge-openwrt-control/issues"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./index.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"index.js",
|
|
26
|
+
"config.schema.json",
|
|
27
|
+
"package.json",
|
|
28
|
+
"CHANGELOG.md",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"homebridge": "^1.8.0 || ^2.0.0 || ^2.0.0-beta.80 || ^2.0.0-alpha.63",
|
|
34
|
+
"node": "^20 || ^22 || ^24 || ^25"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"axios": "^1.13.2"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"homebridge",
|
|
41
|
+
"homebridge-plugin",
|
|
42
|
+
"homekit",
|
|
43
|
+
"openwrt",
|
|
44
|
+
"accesspoint",
|
|
45
|
+
"router",
|
|
46
|
+
"switch"
|
|
47
|
+
|
|
48
|
+
],
|
|
49
|
+
"contributors": [],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
52
|
+
}
|
|
53
|
+
}
|