homebridge-ipark-hb 1.2.2 → 1.2.3
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 +220 -148
- 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,252 @@
|
|
|
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
|
-
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
|
-
});
|
|
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);
|
|
28
194
|
|
|
29
|
-
|
|
195
|
+
service
|
|
196
|
+
.getCharacteristic(Characteristic.On)
|
|
197
|
+
.onGet(this.onGet.bind(this))
|
|
198
|
+
.onSet(this.onSet.bind(this));
|
|
30
199
|
}
|
|
31
|
-
|
|
200
|
+
|
|
201
|
+
async onGet() {
|
|
202
|
+
const { platform, acc } = this;
|
|
203
|
+
|
|
32
204
|
try {
|
|
33
|
-
|
|
205
|
+
if (!platform.token) {
|
|
206
|
+
platform.token = await platform.getAccessToken();
|
|
207
|
+
}
|
|
208
|
+
|
|
34
209
|
const path =
|
|
35
210
|
acc.context.type === "livinglight"
|
|
36
211
|
? `/livinglight/${acc.context.room}/apply`
|
|
37
212
|
: `/light/${acc.context.room}/apply`;
|
|
38
213
|
|
|
39
|
-
const res = await
|
|
40
|
-
if (!res.data
|
|
214
|
+
const res = await platform.http(platform.token).get(path);
|
|
215
|
+
if (!res.data?.units) return false;
|
|
41
216
|
|
|
42
217
|
const device = res.data.units.find(
|
|
43
218
|
(u) => u.unit === acc.context.unit,
|
|
44
219
|
);
|
|
220
|
+
|
|
45
221
|
return device?.state === "on";
|
|
46
222
|
} catch (e) {
|
|
47
|
-
|
|
223
|
+
platform.log.error("GET failed", e.message);
|
|
48
224
|
return false;
|
|
49
225
|
}
|
|
50
226
|
}
|
|
51
|
-
|
|
227
|
+
|
|
228
|
+
async onSet(value) {
|
|
229
|
+
const { platform, acc } = this;
|
|
230
|
+
|
|
52
231
|
try {
|
|
53
|
-
|
|
232
|
+
if (!platform.token) {
|
|
233
|
+
platform.token = await platform.getAccessToken();
|
|
234
|
+
}
|
|
235
|
+
|
|
54
236
|
const path =
|
|
55
237
|
acc.context.type === "livinglight"
|
|
56
238
|
? `/livinglight/${acc.context.room}/apply`
|
|
57
239
|
: `/light/${acc.context.room}/apply`;
|
|
58
240
|
|
|
59
|
-
await
|
|
241
|
+
await platform.http(platform.token).put(path, {
|
|
60
242
|
unit: acc.context.unit,
|
|
61
243
|
state: value ? "on" : "off",
|
|
62
244
|
});
|
|
63
245
|
} catch (e) {
|
|
64
|
-
|
|
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;
|
|
246
|
+
platform.log.error("SET failed", e.message);
|
|
247
|
+
throw e;
|
|
87
248
|
}
|
|
88
249
|
}
|
|
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
250
|
}
|
|
251
|
+
|
|
252
|
+
module.exports = Lightbulb;
|
package/package.json
CHANGED
package/publish
ADDED