homebridge-ipark-hb 1.2.2 → 1.2.4
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/index.js +1 -2
- package/lightbulb.js +249 -138
- package/package.json +1 -1
- package/publish +3 -0
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
let Service, Characteristic;
|
|
2
|
-
const
|
|
2
|
+
const Lightbulb = require("./lightbulb");
|
|
3
3
|
|
|
4
4
|
module.exports = (api) => {
|
|
5
5
|
Service = api.hap.Service;
|
|
@@ -13,7 +13,6 @@ class Platform {
|
|
|
13
13
|
this.config = config;
|
|
14
14
|
this.api = api;
|
|
15
15
|
this.accessories = [];
|
|
16
|
-
this.lightulb = new LightbulbPlugin(log, config, api);
|
|
17
16
|
api.on("didFinishLaunching", async () => {
|
|
18
17
|
await this.initialize();
|
|
19
18
|
});
|
package/lightbulb.js
CHANGED
|
@@ -1,180 +1,291 @@
|
|
|
1
|
+
// const axios = require("axios");
|
|
2
|
+
|
|
3
|
+
// // let Service, Characteristic;
|
|
4
|
+
|
|
5
|
+
// module.exports = (api) => {
|
|
6
|
+
// api.registerPlatform("ipark-hb", "IPARKHB", LightbulbPlugin);
|
|
7
|
+
// };
|
|
8
|
+
|
|
9
|
+
// class LightbulbPlugin {
|
|
10
|
+
// constructor(log, config, api) {
|
|
11
|
+
// this.log = log;
|
|
12
|
+
// this.api = api;
|
|
13
|
+
// this.config = config;
|
|
14
|
+
// this.Service = this.api.hap.Service;
|
|
15
|
+
// this.Characteristic = this.api.hap.Characteristic;
|
|
16
|
+
// this.name = "IPARK Light";
|
|
17
|
+
// this.accessories = [];
|
|
18
|
+
// this.token = null;
|
|
19
|
+
// this.http = (accessToken) =>
|
|
20
|
+
// axios.create({
|
|
21
|
+
// baseURL: "https://idj1.hdc-smart.com/v2/api/features",
|
|
22
|
+
// timeout: 5000,
|
|
23
|
+
// headers: {
|
|
24
|
+
// "access-token": accessToken,
|
|
25
|
+
// "Content-Type": "application/json",
|
|
26
|
+
// },
|
|
27
|
+
// });
|
|
28
|
+
|
|
29
|
+
// api.on("didFinishLaunching", () => this.discoverDevices());
|
|
30
|
+
// }
|
|
31
|
+
// async handleOnGet(acc) {
|
|
32
|
+
// try {
|
|
33
|
+
// this.token = await this.getAccessToken();
|
|
34
|
+
// const path =
|
|
35
|
+
// acc.context.type === "livinglight"
|
|
36
|
+
// ? `/livinglight/${acc.context.room}/apply`
|
|
37
|
+
// : `/light/${acc.context.room}/apply`;
|
|
38
|
+
|
|
39
|
+
// const res = await this.http(this.token).get(path);
|
|
40
|
+
// if (!res.data || !res.data.units) return false;
|
|
41
|
+
|
|
42
|
+
// const device = res.data.units.find(
|
|
43
|
+
// (u) => u.unit === acc.context.unit,
|
|
44
|
+
// );
|
|
45
|
+
// return device?.state === "on";
|
|
46
|
+
// } catch (e) {
|
|
47
|
+
// this.log.error("Failed: Get", e.message);
|
|
48
|
+
// return false;
|
|
49
|
+
// }
|
|
50
|
+
// }
|
|
51
|
+
// async handleOnSet(acc, value) {
|
|
52
|
+
// try {
|
|
53
|
+
// this.token = await this.getAccessToken();
|
|
54
|
+
// const path =
|
|
55
|
+
// acc.context.type === "livinglight"
|
|
56
|
+
// ? `/livinglight/${acc.context.room}/apply`
|
|
57
|
+
// : `/light/${acc.context.room}/apply`;
|
|
58
|
+
|
|
59
|
+
// await this.http(this.token).put(path, {
|
|
60
|
+
// unit: acc.context.unit,
|
|
61
|
+
// state: value ? "on" : "off",
|
|
62
|
+
// });
|
|
63
|
+
// } catch (e) {
|
|
64
|
+
// this.log.error("Failed: Set", e.message);
|
|
65
|
+
// }
|
|
66
|
+
// }
|
|
67
|
+
// configureAccessory(acc) {
|
|
68
|
+
// this.accessories.push(acc);
|
|
69
|
+
// }
|
|
70
|
+
// async getAccessToken() {
|
|
71
|
+
// try {
|
|
72
|
+
// const res = await axios.post(
|
|
73
|
+
// "https://center.hdc-smart.com/v3/auth/login",
|
|
74
|
+
// "V2",
|
|
75
|
+
// {
|
|
76
|
+
// headers: {
|
|
77
|
+
// Authorization: this.config.auth,
|
|
78
|
+
// "X-API-KEY": this.config.apiKey,
|
|
79
|
+
// },
|
|
80
|
+
// },
|
|
81
|
+
// );
|
|
82
|
+
|
|
83
|
+
// return res.data["access-token"];
|
|
84
|
+
// } catch (e) {
|
|
85
|
+
// this.log.error("Authentication failed", e.message);
|
|
86
|
+
// return null;
|
|
87
|
+
// }
|
|
88
|
+
// }
|
|
89
|
+
// async discoverDevices() {
|
|
90
|
+
// this.token = await this.getAccessToken();
|
|
91
|
+
// let allLights = [];
|
|
92
|
+
// // living room
|
|
93
|
+
// try {
|
|
94
|
+
// const res = await this.http(this.token).get(`/livinglight/1/apply`);
|
|
95
|
+
|
|
96
|
+
// if (res.data.result !== "fail") {
|
|
97
|
+
// const roomName = res.data.map?.name || "Living Room";
|
|
98
|
+
// const units = res.data.units || [];
|
|
99
|
+
|
|
100
|
+
// for (const u of units) {
|
|
101
|
+
// allLights.push({
|
|
102
|
+
// id: `living-1-${u.unit}`,
|
|
103
|
+
// type: "livinglight",
|
|
104
|
+
// room: 1,
|
|
105
|
+
// unit: u.unit,
|
|
106
|
+
// name: u.name || `${roomName} ${u.unit}`,
|
|
107
|
+
// });
|
|
108
|
+
// }
|
|
109
|
+
|
|
110
|
+
// this.log.info(`Living room: ${units.length} devices`);
|
|
111
|
+
// }
|
|
112
|
+
// } catch (e) {
|
|
113
|
+
// this.log.error("Living room discovery failed", e.message);
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
// // other rooms
|
|
117
|
+
// let j = 1;
|
|
118
|
+
// while (true) {
|
|
119
|
+
// try {
|
|
120
|
+
// const res = await this.http(this.token).get(
|
|
121
|
+
// `/light/${j}/apply`,
|
|
122
|
+
// );
|
|
123
|
+
// if (res.data.result !== "ok") break;
|
|
124
|
+
|
|
125
|
+
// const roomName = res.data.map?.name || `Room ${j}`;
|
|
126
|
+
// const units = res.data.units || [];
|
|
127
|
+
|
|
128
|
+
// for (const u of units) {
|
|
129
|
+
// allLights.push({
|
|
130
|
+
// id: `room-${j}-${u.unit}`,
|
|
131
|
+
// type: "light",
|
|
132
|
+
// room: j,
|
|
133
|
+
// unit: u.unit,
|
|
134
|
+
// name: u.name || `${roomName} ${u.unit}`,
|
|
135
|
+
// });
|
|
136
|
+
// }
|
|
137
|
+
|
|
138
|
+
// this.log.info(`Room ${j}: ${units.length} devices`);
|
|
139
|
+
// j++;
|
|
140
|
+
// } catch (e) {
|
|
141
|
+
// this.log.error(`Room ${j} discovery failed`, e.message);
|
|
142
|
+
// break;
|
|
143
|
+
// }
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// for (const light of allLights) {
|
|
147
|
+
// const uuid = this.api.hap.uuid.generate(light.id);
|
|
148
|
+
// let acc = this.accessories.find((a) => a.UUID === uuid);
|
|
149
|
+
|
|
150
|
+
// if (!acc) {
|
|
151
|
+
// acc = new this.api.platformAccessory(light.name, uuid);
|
|
152
|
+
// acc.context = light;
|
|
153
|
+
|
|
154
|
+
// this.setupAccessory(acc);
|
|
155
|
+
|
|
156
|
+
// this.api.registerPlatformAccessories("ipark-hb", "IPARKHB", [
|
|
157
|
+
// acc,
|
|
158
|
+
// ]);
|
|
159
|
+
// this.log.info(`Added ${light.name}`);
|
|
160
|
+
// } else {
|
|
161
|
+
// acc.context = light;
|
|
162
|
+
// this.setupAccessory(acc);
|
|
163
|
+
// }
|
|
164
|
+
// }
|
|
165
|
+
// const validUUIDs = allLights.map((l) =>
|
|
166
|
+
// this.api.hap.uuid.generate(l.id),
|
|
167
|
+
// );
|
|
168
|
+
// }
|
|
169
|
+
|
|
170
|
+
// setupAccessory(acc) {
|
|
171
|
+
// const service =
|
|
172
|
+
// acc.getService(this.Service.Lightbulb) ||
|
|
173
|
+
// acc.addService(this.Service.Lightbulb);
|
|
174
|
+
|
|
175
|
+
// service
|
|
176
|
+
// .getCharacteristic(this.Characteristic.On)
|
|
177
|
+
// .onGet(() => this.handleOnGet(acc))
|
|
178
|
+
// .onSet((value) => this.handleOnSet(acc, value));
|
|
179
|
+
// }
|
|
180
|
+
// }
|
|
1
181
|
const axios = require("axios");
|
|
2
182
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.http = (accessToken) =>
|
|
20
|
-
axios.create({
|
|
21
|
-
baseURL: "https://idj1.hdc-smart.com/v2/api/features",
|
|
22
|
-
timeout: 5000,
|
|
23
|
-
headers: {
|
|
24
|
-
"access-token": accessToken,
|
|
25
|
-
"Content-Type": "application/json",
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
api.on("didFinishLaunching", () => this.discoverDevices());
|
|
30
|
-
}
|
|
31
|
-
async handleOnGet(acc) {
|
|
32
|
-
try {
|
|
33
|
-
this.token = await this.getAccessToken();
|
|
34
|
-
const path =
|
|
35
|
-
acc.context.type === "livinglight"
|
|
36
|
-
? `/livinglight/${acc.context.room}/apply`
|
|
37
|
-
: `/light/${acc.context.room}/apply`;
|
|
38
|
-
|
|
39
|
-
const res = await this.http(this.token).get(path);
|
|
40
|
-
if (!res.data || !res.data.units) return false;
|
|
41
|
-
|
|
42
|
-
const device = res.data.units.find(
|
|
43
|
-
(u) => u.unit === acc.context.unit,
|
|
44
|
-
);
|
|
45
|
-
return device?.state === "on";
|
|
46
|
-
} catch (e) {
|
|
47
|
-
this.log.error("Failed: Get", e.message);
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async handleOnSet(acc, value) {
|
|
52
|
-
try {
|
|
53
|
-
this.token = await this.getAccessToken();
|
|
54
|
-
const path =
|
|
55
|
-
acc.context.type === "livinglight"
|
|
56
|
-
? `/livinglight/${acc.context.room}/apply`
|
|
57
|
-
: `/light/${acc.context.room}/apply`;
|
|
58
|
-
|
|
59
|
-
await this.http(this.token).put(path, {
|
|
60
|
-
unit: acc.context.unit,
|
|
61
|
-
state: value ? "on" : "off",
|
|
62
|
-
});
|
|
63
|
-
} catch (e) {
|
|
64
|
-
this.log.error("Failed: Set", e.message);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
configureAccessory(acc) {
|
|
68
|
-
this.accessories.push(acc);
|
|
69
|
-
}
|
|
70
|
-
async getAccessToken() {
|
|
71
|
-
try {
|
|
72
|
-
const res = await axios.post(
|
|
73
|
-
"https://center.hdc-smart.com/v3/auth/login",
|
|
74
|
-
"V2",
|
|
75
|
-
{
|
|
76
|
-
headers: {
|
|
77
|
-
Authorization: this.config.auth,
|
|
78
|
-
"X-API-KEY": this.config.apiKey,
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
return res.data["access-token"];
|
|
84
|
-
} catch (e) {
|
|
85
|
-
this.log.error("Authentication failed", e.message);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
183
|
+
class Lightbulb {
|
|
184
|
+
constructor(platform, acc) {
|
|
185
|
+
this.platform = platform;
|
|
186
|
+
this.acc = acc;
|
|
187
|
+
|
|
188
|
+
const Service = platform.api.hap.Service;
|
|
189
|
+
const Characteristic = platform.api.hap.Characteristic;
|
|
190
|
+
|
|
191
|
+
const service =
|
|
192
|
+
acc.getService(Service.Lightbulb) ||
|
|
193
|
+
acc.addService(Service.Lightbulb);
|
|
194
|
+
|
|
195
|
+
service
|
|
196
|
+
.getCharacteristic(Characteristic.On)
|
|
197
|
+
.onGet(this.onGet.bind(this))
|
|
198
|
+
.onSet(this.onSet.bind(this));
|
|
88
199
|
}
|
|
89
|
-
|
|
90
|
-
|
|
200
|
+
|
|
201
|
+
static async discoverDevices(platform) {
|
|
202
|
+
const token = await platform.getAccessToken();
|
|
203
|
+
if (!token) return [];
|
|
204
|
+
|
|
205
|
+
const http = platform.http(token);
|
|
91
206
|
let allLights = [];
|
|
207
|
+
|
|
92
208
|
// living room
|
|
93
209
|
try {
|
|
94
|
-
const res = await
|
|
95
|
-
|
|
96
|
-
if (res.data.result !== "fail") {
|
|
97
|
-
const roomName = res.data.map?.name || "Living Room";
|
|
210
|
+
const res = await http.get(`/livinglight/1/apply`);
|
|
211
|
+
if (res.data?.result !== "fail") {
|
|
98
212
|
const units = res.data.units || [];
|
|
99
|
-
|
|
100
213
|
for (const u of units) {
|
|
101
214
|
allLights.push({
|
|
102
215
|
id: `living-1-${u.unit}`,
|
|
103
216
|
type: "livinglight",
|
|
104
217
|
room: 1,
|
|
105
218
|
unit: u.unit,
|
|
106
|
-
name: u.name ||
|
|
219
|
+
name: u.name || `Living ${u.unit}`,
|
|
107
220
|
});
|
|
108
221
|
}
|
|
109
|
-
|
|
110
|
-
this.log.info(`Living room: ${units.length} devices`);
|
|
111
222
|
}
|
|
112
|
-
} catch
|
|
113
|
-
this.log.error("Living room discovery failed", e.message);
|
|
114
|
-
}
|
|
223
|
+
} catch {}
|
|
115
224
|
|
|
116
225
|
// other rooms
|
|
117
|
-
let
|
|
226
|
+
let i = 1;
|
|
118
227
|
while (true) {
|
|
119
228
|
try {
|
|
120
|
-
const res = await
|
|
121
|
-
|
|
122
|
-
);
|
|
123
|
-
if (res.data.result !== "ok") break;
|
|
229
|
+
const res = await http.get(`/light/${i}/apply`);
|
|
230
|
+
if (res.data?.result !== "ok") break;
|
|
124
231
|
|
|
125
|
-
const roomName = res.data.map?.name || `Room ${j}`;
|
|
126
232
|
const units = res.data.units || [];
|
|
127
|
-
|
|
128
233
|
for (const u of units) {
|
|
129
234
|
allLights.push({
|
|
130
|
-
id: `room-${
|
|
235
|
+
id: `room-${i}-${u.unit}`,
|
|
131
236
|
type: "light",
|
|
132
|
-
room:
|
|
237
|
+
room: i,
|
|
133
238
|
unit: u.unit,
|
|
134
|
-
name: u.name ||
|
|
239
|
+
name: u.name || `Room ${i} ${u.unit}`,
|
|
135
240
|
});
|
|
136
241
|
}
|
|
137
242
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
} catch (e) {
|
|
141
|
-
this.log.error(`Room ${j} discovery failed`, e.message);
|
|
243
|
+
i++;
|
|
244
|
+
} catch {
|
|
142
245
|
break;
|
|
143
246
|
}
|
|
144
247
|
}
|
|
145
248
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
let acc = this.accessories.find((a) => a.UUID === uuid);
|
|
149
|
-
|
|
150
|
-
if (!acc) {
|
|
151
|
-
acc = new this.api.platformAccessory(light.name, uuid);
|
|
152
|
-
acc.context = light;
|
|
249
|
+
return allLights;
|
|
250
|
+
}
|
|
153
251
|
|
|
154
|
-
|
|
252
|
+
async onGet() {
|
|
253
|
+
const { platform, acc } = this;
|
|
155
254
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
]);
|
|
159
|
-
this.log.info(`Added ${light.name}`);
|
|
160
|
-
} else {
|
|
161
|
-
acc.context = light;
|
|
162
|
-
this.setupAccessory(acc);
|
|
163
|
-
}
|
|
255
|
+
if (!platform.token) {
|
|
256
|
+
platform.token = await platform.getAccessToken();
|
|
164
257
|
}
|
|
165
|
-
|
|
166
|
-
|
|
258
|
+
|
|
259
|
+
const path =
|
|
260
|
+
acc.context.type === "livinglight"
|
|
261
|
+
? `/livinglight/${acc.context.room}/apply`
|
|
262
|
+
: `/light/${acc.context.room}/apply`;
|
|
263
|
+
|
|
264
|
+
const res = await platform.http(platform.token).get(path);
|
|
265
|
+
const device = res.data?.units?.find(
|
|
266
|
+
(u) => u.unit === acc.context.unit,
|
|
167
267
|
);
|
|
268
|
+
|
|
269
|
+
return device?.state === "on";
|
|
168
270
|
}
|
|
169
271
|
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
acc.getService(this.Service.Lightbulb) ||
|
|
173
|
-
acc.addService(this.Service.Lightbulb);
|
|
272
|
+
async onSet(value) {
|
|
273
|
+
const { platform, acc } = this;
|
|
174
274
|
|
|
175
|
-
|
|
176
|
-
.
|
|
177
|
-
|
|
178
|
-
|
|
275
|
+
if (!platform.token) {
|
|
276
|
+
platform.token = await platform.getAccessToken();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const path =
|
|
280
|
+
acc.context.type === "livinglight"
|
|
281
|
+
? `/livinglight/${acc.context.room}/apply`
|
|
282
|
+
: `/light/${acc.context.room}/apply`;
|
|
283
|
+
|
|
284
|
+
await platform.http(platform.token).put(path, {
|
|
285
|
+
unit: acc.context.unit,
|
|
286
|
+
state: value ? "on" : "off",
|
|
287
|
+
});
|
|
179
288
|
}
|
|
180
289
|
}
|
|
290
|
+
|
|
291
|
+
module.exports = Lightbulb;
|
package/package.json
CHANGED
package/publish
ADDED