homebridge-deco 1.0.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/LICENSE +176 -0
- package/README.md +290 -0
- package/config.schema.json +89 -0
- package/dist/decoAPI.d.ts +85 -0
- package/dist/decoAPI.js +288 -0
- package/dist/decoAPI.js.map +1 -0
- package/dist/decoDeviceAccessory.d.ts +21 -0
- package/dist/decoDeviceAccessory.js +73 -0
- package/dist/decoDeviceAccessory.js.map +1 -0
- package/dist/decoDeviceTrackerAccessory.d.ts +22 -0
- package/dist/decoDeviceTrackerAccessory.js +65 -0
- package/dist/decoDeviceTrackerAccessory.js.map +1 -0
- package/dist/decoGuestNetworkAccessory.d.ts +25 -0
- package/dist/decoGuestNetworkAccessory.js +79 -0
- package/dist/decoGuestNetworkAccessory.js.map +1 -0
- package/dist/decoNetworkAccessory.d.ts +21 -0
- package/dist/decoNetworkAccessory.js +63 -0
- package/dist/decoNetworkAccessory.js.map +1 -0
- package/dist/decoRouterAccessory.d.ts +25 -0
- package/dist/decoRouterAccessory.js +65 -0
- package/dist/decoRouterAccessory.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +55 -0
- package/dist/platform.js +264 -0
- package/dist/platform.js.map +1 -0
- package/dist/settings.d.ts +8 -0
- package/dist/settings.js +9 -0
- package/dist/settings.js.map +1 -0
- package/package.json +50 -0
package/dist/decoAPI.js
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
export class DecoAPI {
|
|
3
|
+
log;
|
|
4
|
+
username;
|
|
5
|
+
password;
|
|
6
|
+
token = null;
|
|
7
|
+
baseUrl = 'https://use1-wap.tplinkdeco.com';
|
|
8
|
+
termid;
|
|
9
|
+
lastAuthTime = 0;
|
|
10
|
+
authValidityMs = 3600000; // 1 hour
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.log = config.log;
|
|
13
|
+
this.username = config.username;
|
|
14
|
+
this.password = config.password;
|
|
15
|
+
this.termid = randomUUID();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Authenticate with TP-Link cloud service
|
|
19
|
+
*/
|
|
20
|
+
async authenticate() {
|
|
21
|
+
try {
|
|
22
|
+
// Check if we have a valid token already
|
|
23
|
+
if (this.token && (Date.now() - this.lastAuthTime) < this.authValidityMs) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
this.log.debug('Authenticating with TP-Link cloud...');
|
|
27
|
+
const params = {
|
|
28
|
+
method: 'login',
|
|
29
|
+
params: {
|
|
30
|
+
appType: 'Deco',
|
|
31
|
+
cloudUserName: this.username,
|
|
32
|
+
cloudPassword: this.password,
|
|
33
|
+
terminalUUID: this.termid,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
const response = await this.makeRequest('/', params, false);
|
|
37
|
+
if (response.error_code !== 0) {
|
|
38
|
+
this.log.error('Authentication failed:', response.msg || 'Unknown error');
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (response.result && typeof response.result === 'object' && 'token' in response.result) {
|
|
42
|
+
this.token = response.result.token;
|
|
43
|
+
this.lastAuthTime = Date.now();
|
|
44
|
+
this.log.info('Successfully authenticated with TP-Link cloud');
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
this.log.error('Invalid authentication response');
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
this.log.error('Authentication error:', error);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get list of Deco devices in the network
|
|
57
|
+
*/
|
|
58
|
+
async getDeviceList() {
|
|
59
|
+
try {
|
|
60
|
+
if (!await this.ensureAuthenticated()) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const params = {
|
|
64
|
+
method: 'getDeviceList',
|
|
65
|
+
params: {},
|
|
66
|
+
};
|
|
67
|
+
const response = await this.makeRequest('/', params);
|
|
68
|
+
if (response.error_code !== 0) {
|
|
69
|
+
this.log.error('Failed to get device list:', response.msg);
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
if (response.result && typeof response.result === 'object' && 'deviceList' in response.result) {
|
|
73
|
+
const devices = response.result.deviceList || [];
|
|
74
|
+
this.log.debug(`Found ${devices.length} Deco devices`);
|
|
75
|
+
return devices;
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
this.log.error('Error getting device list:', error);
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get network status including internet connectivity and guest network
|
|
86
|
+
*/
|
|
87
|
+
async getNetworkStatus() {
|
|
88
|
+
try {
|
|
89
|
+
if (!await this.ensureAuthenticated()) {
|
|
90
|
+
return {
|
|
91
|
+
internetOnline: false,
|
|
92
|
+
guestNetworkEnabled: false,
|
|
93
|
+
devices: [],
|
|
94
|
+
clients: [],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const [devices, clients, guestNetwork] = await Promise.all([
|
|
98
|
+
this.getDeviceList(),
|
|
99
|
+
this.getClientList(),
|
|
100
|
+
this.getGuestNetworkStatus(),
|
|
101
|
+
]);
|
|
102
|
+
// Check if any device is online to determine internet status
|
|
103
|
+
const internetOnline = devices.some(d => d.status === 1);
|
|
104
|
+
return {
|
|
105
|
+
internetOnline,
|
|
106
|
+
guestNetworkEnabled: guestNetwork,
|
|
107
|
+
devices,
|
|
108
|
+
clients,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
this.log.error('Error getting network status:', error);
|
|
113
|
+
return {
|
|
114
|
+
internetOnline: false,
|
|
115
|
+
guestNetworkEnabled: false,
|
|
116
|
+
devices: [],
|
|
117
|
+
clients: [],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get list of connected clients
|
|
123
|
+
*/
|
|
124
|
+
async getClientList() {
|
|
125
|
+
try {
|
|
126
|
+
if (!await this.ensureAuthenticated()) {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
const params = {
|
|
130
|
+
method: 'getClientList',
|
|
131
|
+
params: {},
|
|
132
|
+
};
|
|
133
|
+
const response = await this.makeRequest('/', params);
|
|
134
|
+
if (response.error_code !== 0) {
|
|
135
|
+
this.log.debug('Failed to get client list:', response.msg);
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
if (response.result && typeof response.result === 'object' && 'clientList' in response.result) {
|
|
139
|
+
const clients = response.result.clientList || [];
|
|
140
|
+
this.log.debug(`Found ${clients.length} connected clients`);
|
|
141
|
+
return clients;
|
|
142
|
+
}
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
this.log.error('Error getting client list:', error);
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get guest network status
|
|
152
|
+
*/
|
|
153
|
+
async getGuestNetworkStatus() {
|
|
154
|
+
try {
|
|
155
|
+
if (!await this.ensureAuthenticated()) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const params = {
|
|
159
|
+
method: 'getGuestNetwork',
|
|
160
|
+
params: {},
|
|
161
|
+
};
|
|
162
|
+
const response = await this.makeRequest('/', params);
|
|
163
|
+
if (response.error_code !== 0) {
|
|
164
|
+
this.log.debug('Failed to get guest network status:', response.msg);
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (response.result && typeof response.result === 'object' && 'enabled' in response.result) {
|
|
168
|
+
return response.result.enabled === true;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
this.log.debug('Error getting guest network status:', error);
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Toggle guest network on/off
|
|
179
|
+
*/
|
|
180
|
+
async setGuestNetwork(enabled) {
|
|
181
|
+
try {
|
|
182
|
+
if (!await this.ensureAuthenticated()) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const params = {
|
|
186
|
+
method: 'setGuestNetwork',
|
|
187
|
+
params: {
|
|
188
|
+
enabled,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
const response = await this.makeRequest('/', params);
|
|
192
|
+
if (response.error_code !== 0) {
|
|
193
|
+
this.log.error('Failed to set guest network:', response.msg);
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
this.log.info(`Guest network ${enabled ? 'enabled' : 'disabled'}`);
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
this.log.error('Error setting guest network:', error);
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Check if a specific device (by MAC) is connected
|
|
206
|
+
*/
|
|
207
|
+
async isDeviceConnected(mac) {
|
|
208
|
+
try {
|
|
209
|
+
const clients = await this.getClientList();
|
|
210
|
+
const normalizedMac = mac.toLowerCase().replace(/[:-]/g, '');
|
|
211
|
+
return clients.some(client => {
|
|
212
|
+
const clientMac = client.mac.toLowerCase().replace(/[:-]/g, '');
|
|
213
|
+
return clientMac === normalizedMac && client.online;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
this.log.error('Error checking device connection:', error);
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Reboot a specific Deco device
|
|
223
|
+
*/
|
|
224
|
+
async rebootDevice(deviceId) {
|
|
225
|
+
try {
|
|
226
|
+
if (!await this.ensureAuthenticated()) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
const params = {
|
|
230
|
+
method: 'reboot',
|
|
231
|
+
params: {
|
|
232
|
+
deviceId,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
const response = await this.makeRequest('/', params);
|
|
236
|
+
if (response.error_code !== 0) {
|
|
237
|
+
this.log.error('Failed to reboot device:', response.msg);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
this.log.info(`Rebooted device ${deviceId}`);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
this.log.error('Error rebooting device:', error);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Make HTTP request to TP-Link API
|
|
250
|
+
*/
|
|
251
|
+
async makeRequest(endpoint, params, requireAuth = true) {
|
|
252
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
253
|
+
const headers = {
|
|
254
|
+
'Content-Type': 'application/json',
|
|
255
|
+
'User-Agent': 'Deco/3.0 (iPhone; iOS 15.0; Scale/3.00)',
|
|
256
|
+
};
|
|
257
|
+
if (requireAuth && this.token) {
|
|
258
|
+
headers.Authorization = `Bearer ${this.token}`;
|
|
259
|
+
}
|
|
260
|
+
const body = JSON.stringify(params);
|
|
261
|
+
try {
|
|
262
|
+
const response = await fetch(url, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
headers,
|
|
265
|
+
body,
|
|
266
|
+
});
|
|
267
|
+
if (!response.ok) {
|
|
268
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
269
|
+
}
|
|
270
|
+
const data = await response.json();
|
|
271
|
+
return data;
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
this.log.error('API request failed:', error);
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Ensure we have a valid authentication token
|
|
280
|
+
*/
|
|
281
|
+
async ensureAuthenticated() {
|
|
282
|
+
if (!this.token || (Date.now() - this.lastAuthTime) >= this.authValidityMs) {
|
|
283
|
+
return await this.authenticate();
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=decoAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoAPI.js","sourceRoot":"","sources":["../src/decoAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import type { DecoHomebridgePlatform } from './platform.js';
|
|
3
|
+
/**
|
|
4
|
+
* Deco Device Accessory
|
|
5
|
+
* Represents an individual Deco mesh unit with status indicator
|
|
6
|
+
*/
|
|
7
|
+
export declare class DecoDeviceAccessory {
|
|
8
|
+
private readonly platform;
|
|
9
|
+
private readonly accessory;
|
|
10
|
+
private service;
|
|
11
|
+
private device;
|
|
12
|
+
constructor(platform: DecoHomebridgePlatform, accessory: PlatformAccessory);
|
|
13
|
+
/**
|
|
14
|
+
* Get device online status
|
|
15
|
+
*/
|
|
16
|
+
getContactSensorState(): Promise<CharacteristicValue>;
|
|
17
|
+
/**
|
|
18
|
+
* Update device status
|
|
19
|
+
*/
|
|
20
|
+
private updateStatus;
|
|
21
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deco Device Accessory
|
|
3
|
+
* Represents an individual Deco mesh unit with status indicator
|
|
4
|
+
*/
|
|
5
|
+
export class DecoDeviceAccessory {
|
|
6
|
+
platform;
|
|
7
|
+
accessory;
|
|
8
|
+
service;
|
|
9
|
+
device;
|
|
10
|
+
constructor(platform, accessory) {
|
|
11
|
+
this.platform = platform;
|
|
12
|
+
this.accessory = accessory;
|
|
13
|
+
this.device = accessory.context.device;
|
|
14
|
+
// Set accessory information
|
|
15
|
+
this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
16
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'TP-Link')
|
|
17
|
+
.setCharacteristic(this.platform.Characteristic.Model, this.device.deviceModel || 'Deco')
|
|
18
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.device.mac || 'Unknown');
|
|
19
|
+
// Use Contact Sensor to indicate if Deco unit is online
|
|
20
|
+
this.service = this.accessory.getService(this.platform.Service.ContactSensor) ||
|
|
21
|
+
this.accessory.addService(this.platform.Service.ContactSensor);
|
|
22
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.device.deviceName);
|
|
23
|
+
// Register handlers
|
|
24
|
+
this.service.getCharacteristic(this.platform.Characteristic.ContactSensorState)
|
|
25
|
+
.onGet(this.getContactSensorState.bind(this));
|
|
26
|
+
// Update status
|
|
27
|
+
this.updateStatus();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get device online status
|
|
31
|
+
*/
|
|
32
|
+
async getContactSensorState() {
|
|
33
|
+
try {
|
|
34
|
+
const status = await this.platform.api_client.getNetworkStatus();
|
|
35
|
+
const device = status.devices.find(d => d.deviceId === this.device.deviceId);
|
|
36
|
+
if (device) {
|
|
37
|
+
this.device = device;
|
|
38
|
+
this.accessory.context.device = device;
|
|
39
|
+
// CONTACT_DETECTED (0) = online, CONTACT_NOT_DETECTED (1) = offline
|
|
40
|
+
return device.status === 1 ?
|
|
41
|
+
this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED :
|
|
42
|
+
this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
43
|
+
}
|
|
44
|
+
return this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
this.platform.log.error('Error getting device status:', error);
|
|
48
|
+
return this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update device status
|
|
53
|
+
*/
|
|
54
|
+
async updateStatus() {
|
|
55
|
+
try {
|
|
56
|
+
const status = await this.platform.api_client.getNetworkStatus();
|
|
57
|
+
const device = status.devices.find(d => d.deviceId === this.device.deviceId);
|
|
58
|
+
if (device) {
|
|
59
|
+
this.device = device;
|
|
60
|
+
this.accessory.context.device = device;
|
|
61
|
+
const state = device.status === 1 ?
|
|
62
|
+
this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED :
|
|
63
|
+
this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
64
|
+
this.service.updateCharacteristic(this.platform.Characteristic.ContactSensorState, state);
|
|
65
|
+
this.platform.log.debug(`Device ${device.deviceName}:`, device.status === 1 ? 'Online' : 'Offline');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.platform.log.error('Error updating device status:', error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=decoDeviceAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoDeviceAccessory.js","sourceRoot":"","sources":["../src/decoDeviceAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import type { DecoHomebridgePlatform } from './platform.js';
|
|
3
|
+
/**
|
|
4
|
+
* Device Tracker Accessory
|
|
5
|
+
* Tracks specific devices by MAC address and reports as Occupancy Sensor
|
|
6
|
+
*/
|
|
7
|
+
export declare class DecoDeviceTrackerAccessory {
|
|
8
|
+
private readonly platform;
|
|
9
|
+
private readonly accessory;
|
|
10
|
+
private service;
|
|
11
|
+
private device;
|
|
12
|
+
private isConnected;
|
|
13
|
+
constructor(platform: DecoHomebridgePlatform, accessory: PlatformAccessory);
|
|
14
|
+
/**
|
|
15
|
+
* Check if device is connected
|
|
16
|
+
*/
|
|
17
|
+
getOccupancyDetected(): Promise<CharacteristicValue>;
|
|
18
|
+
/**
|
|
19
|
+
* Update device connection status
|
|
20
|
+
*/
|
|
21
|
+
private updateStatus;
|
|
22
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Tracker Accessory
|
|
3
|
+
* Tracks specific devices by MAC address and reports as Occupancy Sensor
|
|
4
|
+
*/
|
|
5
|
+
export class DecoDeviceTrackerAccessory {
|
|
6
|
+
platform;
|
|
7
|
+
accessory;
|
|
8
|
+
service;
|
|
9
|
+
device;
|
|
10
|
+
isConnected = false;
|
|
11
|
+
constructor(platform, accessory) {
|
|
12
|
+
this.platform = platform;
|
|
13
|
+
this.accessory = accessory;
|
|
14
|
+
this.device = accessory.context.device;
|
|
15
|
+
// Set accessory information
|
|
16
|
+
this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
17
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Device Tracker')
|
|
18
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'Network Device')
|
|
19
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.device.mac);
|
|
20
|
+
// Use Occupancy Sensor to indicate if device is connected
|
|
21
|
+
this.service = this.accessory.getService(this.platform.Service.OccupancySensor) ||
|
|
22
|
+
this.accessory.addService(this.platform.Service.OccupancySensor);
|
|
23
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.device.name);
|
|
24
|
+
// Register handlers
|
|
25
|
+
this.service.getCharacteristic(this.platform.Characteristic.OccupancyDetected)
|
|
26
|
+
.onGet(this.getOccupancyDetected.bind(this));
|
|
27
|
+
// Update status
|
|
28
|
+
this.updateStatus();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if device is connected
|
|
32
|
+
*/
|
|
33
|
+
async getOccupancyDetected() {
|
|
34
|
+
try {
|
|
35
|
+
const isConnected = await this.platform.api_client.isDeviceConnected(this.device.mac);
|
|
36
|
+
this.isConnected = isConnected;
|
|
37
|
+
// OCCUPANCY_DETECTED (1) = connected, OCCUPANCY_NOT_DETECTED (0) = not connected
|
|
38
|
+
return isConnected ?
|
|
39
|
+
this.platform.Characteristic.OccupancyDetected.OCCUPANCY_DETECTED :
|
|
40
|
+
this.platform.Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.platform.log.error('Error checking device connection:', error);
|
|
44
|
+
return this.platform.Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Update device connection status
|
|
49
|
+
*/
|
|
50
|
+
async updateStatus() {
|
|
51
|
+
try {
|
|
52
|
+
const isConnected = await this.platform.api_client.isDeviceConnected(this.device.mac);
|
|
53
|
+
this.isConnected = isConnected;
|
|
54
|
+
const state = isConnected ?
|
|
55
|
+
this.platform.Characteristic.OccupancyDetected.OCCUPANCY_DETECTED :
|
|
56
|
+
this.platform.Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED;
|
|
57
|
+
this.service.updateCharacteristic(this.platform.Characteristic.OccupancyDetected, state);
|
|
58
|
+
this.platform.log.debug(`Device ${this.device.name} (${this.device.mac}):`, isConnected ? 'Connected' : 'Not connected');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
this.platform.log.error('Error updating device connection status:', error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=decoDeviceTrackerAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoDeviceTrackerAccessory.js","sourceRoot":"","sources":["../src/decoDeviceTrackerAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import type { DecoHomebridgePlatform } from './platform.js';
|
|
3
|
+
/**
|
|
4
|
+
* Guest Network Accessory
|
|
5
|
+
* Exposes guest network control as a Switch
|
|
6
|
+
*/
|
|
7
|
+
export declare class DecoGuestNetworkAccessory {
|
|
8
|
+
private readonly platform;
|
|
9
|
+
private readonly accessory;
|
|
10
|
+
private service;
|
|
11
|
+
private guestNetworkEnabled;
|
|
12
|
+
constructor(platform: DecoHomebridgePlatform, accessory: PlatformAccessory);
|
|
13
|
+
/**
|
|
14
|
+
* Get guest network on/off state
|
|
15
|
+
*/
|
|
16
|
+
getOn(): Promise<CharacteristicValue>;
|
|
17
|
+
/**
|
|
18
|
+
* Set guest network on/off
|
|
19
|
+
*/
|
|
20
|
+
setOn(value: CharacteristicValue): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Update status periodically
|
|
23
|
+
*/
|
|
24
|
+
private updateStatus;
|
|
25
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guest Network Accessory
|
|
3
|
+
* Exposes guest network control as a Switch
|
|
4
|
+
*/
|
|
5
|
+
export class DecoGuestNetworkAccessory {
|
|
6
|
+
platform;
|
|
7
|
+
accessory;
|
|
8
|
+
service;
|
|
9
|
+
guestNetworkEnabled = false;
|
|
10
|
+
constructor(platform, accessory) {
|
|
11
|
+
this.platform = platform;
|
|
12
|
+
this.accessory = accessory;
|
|
13
|
+
// Set accessory information
|
|
14
|
+
this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
15
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'TP-Link')
|
|
16
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'Deco Guest Network')
|
|
17
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, 'GUEST-001');
|
|
18
|
+
// Get or create Switch service
|
|
19
|
+
this.service = this.accessory.getService(this.platform.Service.Switch) ||
|
|
20
|
+
this.accessory.addService(this.platform.Service.Switch);
|
|
21
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, 'Guest Network');
|
|
22
|
+
// Register handlers
|
|
23
|
+
this.service.getCharacteristic(this.platform.Characteristic.On)
|
|
24
|
+
.onGet(this.getOn.bind(this))
|
|
25
|
+
.onSet(this.setOn.bind(this));
|
|
26
|
+
// Initialize status
|
|
27
|
+
this.updateStatus();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get guest network on/off state
|
|
31
|
+
*/
|
|
32
|
+
async getOn() {
|
|
33
|
+
try {
|
|
34
|
+
const enabled = await this.platform.api_client.getGuestNetworkStatus();
|
|
35
|
+
this.guestNetworkEnabled = enabled;
|
|
36
|
+
return enabled;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
this.platform.log.error('Error getting guest network status:', error);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set guest network on/off
|
|
45
|
+
*/
|
|
46
|
+
async setOn(value) {
|
|
47
|
+
try {
|
|
48
|
+
const enabled = value;
|
|
49
|
+
const success = await this.platform.api_client.setGuestNetwork(enabled);
|
|
50
|
+
if (success) {
|
|
51
|
+
this.guestNetworkEnabled = enabled;
|
|
52
|
+
this.platform.log.info('Guest network', enabled ? 'enabled' : 'disabled');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.platform.log.error('Failed to set guest network state');
|
|
56
|
+
throw new Error('Failed to set guest network');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
this.platform.log.error('Error setting guest network:', error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Update status periodically
|
|
66
|
+
*/
|
|
67
|
+
async updateStatus() {
|
|
68
|
+
try {
|
|
69
|
+
const enabled = await this.platform.api_client.getGuestNetworkStatus();
|
|
70
|
+
this.guestNetworkEnabled = enabled;
|
|
71
|
+
this.service.updateCharacteristic(this.platform.Characteristic.On, enabled);
|
|
72
|
+
this.platform.log.debug('Guest network:', enabled ? 'Enabled' : 'Disabled');
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.platform.log.error('Error updating guest network status:', error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=decoGuestNetworkAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoGuestNetworkAccessory.js","sourceRoot":"","sources":["../src/decoGuestNetworkAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import type { DecoHomebridgePlatform } from './platform.js';
|
|
3
|
+
/**
|
|
4
|
+
* Network Status Accessory
|
|
5
|
+
* Exposes internet connectivity as a Contact Sensor (open = online, closed = offline)
|
|
6
|
+
*/
|
|
7
|
+
export declare class DecoNetworkAccessory {
|
|
8
|
+
private readonly platform;
|
|
9
|
+
private readonly accessory;
|
|
10
|
+
private service;
|
|
11
|
+
private internetOnline;
|
|
12
|
+
constructor(platform: DecoHomebridgePlatform, accessory: PlatformAccessory);
|
|
13
|
+
/**
|
|
14
|
+
* Get contact sensor state (CONTACT_DETECTED = online, CONTACT_NOT_DETECTED = offline)
|
|
15
|
+
*/
|
|
16
|
+
getContactSensorState(): Promise<CharacteristicValue>;
|
|
17
|
+
/**
|
|
18
|
+
* Periodically update status
|
|
19
|
+
*/
|
|
20
|
+
private updateStatus;
|
|
21
|
+
}
|