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.
Files changed (4) hide show
  1. package/index.js +1 -2
  2. package/lightbulb.js +249 -138
  3. package/package.json +1 -1
  4. package/publish +3 -0
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  let Service, Characteristic;
2
- const LightbulbPlugin = require("./lightbulb");
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
- // 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
- }
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
- async discoverDevices() {
90
- this.token = await this.getAccessToken();
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 this.http(this.token).get(`/livinglight/1/apply`);
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 || `${roomName} ${u.unit}`,
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 (e) {
113
- this.log.error("Living room discovery failed", e.message);
114
- }
223
+ } catch {}
115
224
 
116
225
  // other rooms
117
- let j = 1;
226
+ let i = 1;
118
227
  while (true) {
119
228
  try {
120
- const res = await this.http(this.token).get(
121
- `/light/${j}/apply`,
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-${j}-${u.unit}`,
235
+ id: `room-${i}-${u.unit}`,
131
236
  type: "light",
132
- room: j,
237
+ room: i,
133
238
  unit: u.unit,
134
- name: u.name || `${roomName} ${u.unit}`,
239
+ name: u.name || `Room ${i} ${u.unit}`,
135
240
  });
136
241
  }
137
242
 
138
- this.log.info(`Room ${j}: ${units.length} devices`);
139
- j++;
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
- 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;
249
+ return allLights;
250
+ }
153
251
 
154
- this.setupAccessory(acc);
252
+ async onGet() {
253
+ const { platform, acc } = this;
155
254
 
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
- }
255
+ if (!platform.token) {
256
+ platform.token = await platform.getAccessToken();
164
257
  }
165
- const validUUIDs = allLights.map((l) =>
166
- this.api.hap.uuid.generate(l.id),
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
- setupAccessory(acc) {
171
- const service =
172
- acc.getService(this.Service.Lightbulb) ||
173
- acc.addService(this.Service.Lightbulb);
272
+ async onSet(value) {
273
+ const { platform, acc } = this;
174
274
 
175
- service
176
- .getCharacteristic(this.Characteristic.On)
177
- .onGet(() => this.handleOnGet(acc))
178
- .onSet((value) => this.handleOnSet(acc, value));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-ipark-hb",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/publish ADDED
@@ -0,0 +1,3 @@
1
+ ./update $1
2
+ npm version $2
3
+ npm publish