homebridge-smarthq-client 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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/Readme.md +138 -0
  3. package/config.schema.json +146 -0
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.js +9 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/platform.d.ts +40 -0
  8. package/dist/platform.js +243 -0
  9. package/dist/platform.js.map +1 -0
  10. package/dist/refrigerator/controlLock.d.ts +19 -0
  11. package/dist/refrigerator/controlLock.js +85 -0
  12. package/dist/refrigerator/controlLock.js.map +1 -0
  13. package/dist/refrigerator/convertibleDrawer.d.ts +27 -0
  14. package/dist/refrigerator/convertibleDrawer.js +317 -0
  15. package/dist/refrigerator/convertibleDrawer.js.map +1 -0
  16. package/dist/refrigerator/dispenserLight.d.ts +19 -0
  17. package/dist/refrigerator/dispenserLight.js +85 -0
  18. package/dist/refrigerator/dispenserLight.js.map +1 -0
  19. package/dist/refrigerator/energy.d.ts +19 -0
  20. package/dist/refrigerator/energy.js +93 -0
  21. package/dist/refrigerator/energy.js.map +1 -0
  22. package/dist/refrigerator/freezer.d.ts +41 -0
  23. package/dist/refrigerator/freezer.js +188 -0
  24. package/dist/refrigerator/freezer.js.map +1 -0
  25. package/dist/refrigerator/iceMaker.d.ts +19 -0
  26. package/dist/refrigerator/iceMaker.js +81 -0
  27. package/dist/refrigerator/iceMaker.js.map +1 -0
  28. package/dist/refrigerator/interiorLight.d.ts +21 -0
  29. package/dist/refrigerator/interiorLight.js +100 -0
  30. package/dist/refrigerator/interiorLight.js.map +1 -0
  31. package/dist/refrigerator/refrigerator.d.ts +41 -0
  32. package/dist/refrigerator/refrigerator.js +204 -0
  33. package/dist/refrigerator/refrigerator.js.map +1 -0
  34. package/dist/refrigerator/refrigeratorAlerts.d.ts +36 -0
  35. package/dist/refrigerator/refrigeratorAlerts.js +204 -0
  36. package/dist/refrigerator/refrigeratorAlerts.js.map +1 -0
  37. package/dist/refrigerator/sabbathMode.d.ts +20 -0
  38. package/dist/refrigerator/sabbathMode.js +91 -0
  39. package/dist/refrigerator/sabbathMode.js.map +1 -0
  40. package/dist/refrigerator/temperatureUnits.d.ts +21 -0
  41. package/dist/refrigerator/temperatureUnits.js +147 -0
  42. package/dist/refrigerator/temperatureUnits.js.map +1 -0
  43. package/dist/refrigerator/turboCoolMode.d.ts +23 -0
  44. package/dist/refrigerator/turboCoolMode.js +134 -0
  45. package/dist/refrigerator/turboCoolMode.js.map +1 -0
  46. package/dist/refrigerator/waterFilter.d.ts +19 -0
  47. package/dist/refrigerator/waterFilter.js +89 -0
  48. package/dist/refrigerator/waterFilter.js.map +1 -0
  49. package/dist/refrigeratorServices.d.ts +5 -0
  50. package/dist/refrigeratorServices.js +54 -0
  51. package/dist/refrigeratorServices.js.map +1 -0
  52. package/dist/settings.d.ts +12 -0
  53. package/dist/settings.js +13 -0
  54. package/dist/settings.js.map +1 -0
  55. package/dist/smartHqApi.d.ts +29 -0
  56. package/dist/smartHqApi.js +267 -0
  57. package/dist/smartHqApi.js.map +1 -0
  58. package/dist/smarthq-types.d.ts +29 -0
  59. package/dist/smarthq-types.js +2 -0
  60. package/dist/smarthq-types.js.map +1 -0
  61. package/eslint.config.js +12 -0
  62. package/images/homebridge.svg +1 -0
  63. package/package.json +61 -0
  64. package/src/@types/homebridge-lib.d.ts +14 -0
  65. package/src/index.ts +11 -0
  66. package/src/platform.ts +300 -0
  67. package/src/refrigerator/controlLock.ts +103 -0
  68. package/src/refrigerator/convertibleDrawer.ts +381 -0
  69. package/src/refrigerator/dispenserLight.ts +103 -0
  70. package/src/refrigerator/energy.ts +106 -0
  71. package/src/refrigerator/freezer.ts +227 -0
  72. package/src/refrigerator/iceMaker.ts +100 -0
  73. package/src/refrigerator/interiorLight.ts +118 -0
  74. package/src/refrigerator/refrigerator.ts +241 -0
  75. package/src/refrigerator/refrigeratorAlerts.ts +228 -0
  76. package/src/refrigerator/sabbathMode.ts +111 -0
  77. package/src/refrigerator/temperatureUnits.ts +178 -0
  78. package/src/refrigerator/turboCoolMode.ts +164 -0
  79. package/src/refrigerator/waterFilter.ts +107 -0
  80. package/src/refrigeratorServices.ts +60 -0
  81. package/src/settings.ts +14 -0
  82. package/src/smartHqApi.ts +305 -0
  83. package/src/smarthq-types.ts +31 -0
  84. package/tsconfig.json +24 -0
@@ -0,0 +1,381 @@
1
+ import { CharacteristicValue, PlatformAccessory, Logging } from 'homebridge';
2
+ import { SmartHqPlatform } from '../platform.js';
3
+ import { SmartHqApi } from '../smartHqApi.js';
4
+ import { DevService } from '../smarthq-types.js';
5
+
6
+ /**
7
+ * Platform Accessory
8
+ * An instance of this class is created for each accessory your platform registers
9
+ * Each accessory may expose multiple services of different service types.
10
+ */
11
+ export class ConvertibleDrawer {
12
+ private readonly smartHqApi: SmartHqApi;
13
+
14
+ //------------------- Convertible Drawer Temperature Service -----------------------
15
+ private convertibleDrawerMode = {
16
+ MEAT: "cloud.smarthq.type.mode.convertibledrawer.mode3",
17
+ BEVERAGES: "cloud.smarthq.type.mode.convertibledrawer.mode4",
18
+ SNACKS: "cloud.smarthq.type.mode.convertibledrawer.mode5",
19
+ WINE: "cloud.smarthq.type.mode.convertibledrawer.mode6",
20
+ };
21
+
22
+ private log : Logging;
23
+
24
+ constructor(
25
+ private readonly platform: SmartHqPlatform,
26
+ private readonly accessory: PlatformAccessory,
27
+ public readonly deviceServices: DevService[],
28
+ public readonly deviceId: string
29
+ ) {
30
+ this.platform = platform;
31
+ this.accessory = accessory;
32
+ this.deviceServices = deviceServices;
33
+ this.deviceId = deviceId;
34
+ this.log = platform.log;
35
+
36
+ this.smartHqApi = new SmartHqApi(this.platform);
37
+
38
+ //=====================================================================================
39
+ // Check to see if the device has any supported Convertible Drawer services
40
+ // If not, then don't add services for device that doesn't support it
41
+ //=====================================================================================
42
+
43
+ if (!this.platform.deviceSupportsThisService(this.deviceServices,
44
+ 'cloud.smarthq.device.refrigerator.convertibledrawer',
45
+ 'cloud.smarthq.service.mode',
46
+ 'cloud.smarthq.domain.mode.selection')) {
47
+ this.log.info('No supported Convertible Drawer services found for device: ' + this.accessory.displayName);
48
+ return;
49
+ }
50
+ this.platform.debug('green', 'Adding Convertible Drawer Switches');
51
+
52
+ // set accessory information
53
+ this.accessory.getService(this.platform.Service.AccessoryInformation)!
54
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'GE')
55
+ .setCharacteristic(this.platform.Characteristic.Model, accessory.context.device.model || 'Default-Model')
56
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.context.device.serial || 'Default-Serial');
57
+
58
+
59
+ //=====================================================================================
60
+ // create some new Switch services for the Refrigerator to be used like radio buttons
61
+ // to set the Convertible Drawer modes (Snacks, Meat, Beverages, Wine)
62
+ //=====================================================================================
63
+ let displayName = "Drawer Meat";
64
+
65
+ const convertibleDrawerMeat = this.accessory.getService(displayName)
66
+ || this.accessory.addService(this.platform.Service.Switch, displayName, 'drawer-mode-3');
67
+ convertibleDrawerMeat.setCharacteristic(this.platform.Characteristic.Name, displayName);
68
+ convertibleDrawerMeat.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
69
+ convertibleDrawerMeat.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
70
+ displayName = "Drawer Beverages";
71
+
72
+ const convertibleDrawerBeverages = this.accessory.getService(displayName)
73
+ || this.accessory.addService(this.platform.Service.Switch, displayName, 'drawer-mode-4');
74
+ convertibleDrawerBeverages.setCharacteristic(this.platform.Characteristic.Name, displayName);
75
+ convertibleDrawerBeverages.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
76
+ convertibleDrawerBeverages.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
77
+
78
+ displayName = "Drawer Snacks";
79
+
80
+ const convertibleDrawerSnacks = this.accessory.getService(displayName)
81
+ || this.accessory.addService(this.platform.Service.Switch, displayName, 'drawer-mode-5');
82
+ convertibleDrawerSnacks.setCharacteristic(this.platform.Characteristic.Name, displayName);
83
+ convertibleDrawerSnacks.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
84
+ convertibleDrawerSnacks.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
85
+
86
+ displayName = "Drawer Wine";
87
+ const convertibleDrawerWine = this.accessory.getService(displayName)
88
+ || this.accessory.addService(this.platform.Service.Switch, displayName, 'drawer-mode-6');
89
+ convertibleDrawerWine.setCharacteristic(this.platform.Characteristic.Name, displayName);
90
+ convertibleDrawerWine.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
91
+ convertibleDrawerWine.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
92
+
93
+ // create handlers for required characteristics
94
+ convertibleDrawerSnacks.getCharacteristic(this.platform.Characteristic.On)
95
+ .onGet(this.getConvertibleDrawerSnacks.bind(this))
96
+ .onSet(this.setConvertibleDrawerSnacks.bind(this));
97
+
98
+ convertibleDrawerMeat.getCharacteristic(this.platform.Characteristic.On)
99
+ .onGet(this.getConvertibleDrawerMeat.bind(this))
100
+ .onSet(this.setConvertibleDrawerMeat.bind(this));
101
+
102
+ convertibleDrawerBeverages.getCharacteristic(this.platform.Characteristic.On)
103
+ .onGet(this.getConvertibleDrawerBeverages.bind(this))
104
+ .onSet(this.setConvertibleDrawerBeverages.bind(this));
105
+
106
+ convertibleDrawerWine.getCharacteristic(this.platform.Characteristic.On)
107
+ .onGet(this.getConvertibleDrawerWine.bind(this))
108
+ .onSet(this.setConvertibleDrawerWine.bind(this));
109
+
110
+ // Service for Convertible Drawer Temperature Sensor
111
+
112
+ displayName = "Drawer Temp";
113
+ const drawerTemperature = this.accessory.getService(displayName)
114
+ || this.accessory.addService(this.platform.Service.TemperatureSensor, displayName, 'drawer-temp-1');
115
+ drawerTemperature.setCharacteristic(this.platform.Characteristic.Name, displayName);
116
+ drawerTemperature.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
117
+ drawerTemperature.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
118
+
119
+ drawerTemperature.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
120
+ .onGet(this.getDrawerTemperature.bind(this));
121
+
122
+ }
123
+
124
+ //=====================================================================================
125
+ async getDrawerTemperature(): Promise<CharacteristicValue> {
126
+ let temp = 0;
127
+ let mode = '0';
128
+
129
+ // First you need to find which mode is set for the Convertible Drawer
130
+
131
+ for (const service of this.deviceServices) {
132
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.convertibledrawer'
133
+ && service.serviceType === 'cloud.smarthq.service.mode') {
134
+
135
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
136
+ if (state == null || !state?.mode) {
137
+ this.platform.debug('blue', 'No mode returned from getDrawerTemperature state');
138
+ break; // an invalid mode value will be used below so no match will be found
139
+ }
140
+ const result = state?.mode.lastIndexOf(".");
141
+ mode = state?.mode.slice(result + 1);
142
+ break;
143
+ }
144
+ }
145
+
146
+ // Add the 'mode' to serviceDeviceType to get the correct temperature service
147
+
148
+ for (const service of this.deviceServices) {
149
+ if (service.serviceDeviceType === `cloud.smarthq.device.refrigerator.convertibledrawer.${mode}`
150
+ && service.serviceType === 'cloud.smarthq.service.temperature') {
151
+
152
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
153
+ if (state == null || !state?.celsiusConverted) {
154
+ this.platform.debug('blue', 'No celsiusConverted returned from getDrawerTemperature state');
155
+ return false;
156
+ }
157
+ temp = state?.celsiusConverted;
158
+ break;
159
+ }
160
+ }
161
+ return temp;
162
+ }
163
+
164
+ //=====================================================================================
165
+ async getConvertibleDrawerSnacks(): Promise<CharacteristicValue> {
166
+ // Find current mode and return true if = mode5 (Snacks)
167
+ const snacks = 'cloud.smarthq.type.mode.convertibledrawer.mode5';
168
+ let isOn = false;
169
+
170
+ for (const service of this.deviceServices) {
171
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.convertibledrawer'
172
+ && service.serviceType === 'cloud.smarthq.service.mode') {
173
+
174
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
175
+ if (state == null || !state?.mode) {
176
+ this.platform.debug('blue', 'No mode returned from getConvertibleDrawerSnacks state');
177
+ return false;
178
+ }
179
+
180
+ if (state?.mode === snacks) {
181
+ isOn = true;
182
+ }
183
+ break;
184
+ }
185
+ }
186
+ return isOn;
187
+ }
188
+
189
+ //=====================================================================================
190
+ async getConvertibleDrawerMeat(): Promise<CharacteristicValue> {
191
+ const meat = 'cloud.smarthq.type.mode.convertibledrawer.mode3';
192
+ // Find current mode and return true if = mode3 (Meat)
193
+ let isOn = false;
194
+
195
+ for (const service of this.deviceServices) {
196
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.convertibledrawer'
197
+ && service.serviceType === 'cloud.smarthq.service.mode') {
198
+
199
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
200
+ if (state == null || !state?.mode) {
201
+ this.platform.debug('blue', 'No mode returned from getConvertibleDrawerMeat state');
202
+ return false;
203
+ }
204
+
205
+ if (state?.mode === meat) {
206
+ isOn = true;
207
+ }
208
+ break;
209
+ }
210
+ }
211
+ return isOn;
212
+ }
213
+
214
+ //=====================================================================================
215
+ async getConvertibleDrawerBeverages(): Promise<CharacteristicValue> {
216
+ const beverages = 'cloud.smarthq.type.mode.convertibledrawer.mode4';
217
+ // Find current mode and return true if = mode4 (Beverages)
218
+ let isOn = false;
219
+
220
+ for (const service of this.deviceServices) {
221
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.convertibledrawer'
222
+ && service.serviceType === 'cloud.smarthq.service.mode') {
223
+
224
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
225
+ if (state == null || !state?.mode) {
226
+ this.platform.debug('blue', 'No mode returned from getConvertibleDrawerBeverages state');
227
+ return false;
228
+ }
229
+
230
+ if (state.mode === beverages) {
231
+ isOn = true;
232
+ }
233
+ break;
234
+ }
235
+ }
236
+ return isOn;
237
+ }
238
+
239
+ //=====================================================================================
240
+ async getConvertibleDrawerWine(): Promise<CharacteristicValue> {
241
+ const wine = 'cloud.smarthq.type.mode.convertibledrawer.mode6';
242
+ // Find current mode and return true if = mode6 (Wine)
243
+ let isOn = false;
244
+
245
+ for (const service of this.deviceServices) {
246
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.convertibledrawer'
247
+ && service.serviceType === 'cloud.smarthq.service.mode') {
248
+
249
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
250
+ if (state == null || !state?.mode) {
251
+ this.platform.debug('blue', 'No mode returned from getConvertibleDrawerWine state');
252
+ return false;
253
+ }
254
+
255
+ if (state.mode === wine) {
256
+ isOn = true;
257
+ }
258
+ break;
259
+ }
260
+ }
261
+ return isOn;
262
+ }
263
+
264
+ //=====================================================================================
265
+ async setConvertibleDrawerMeat(value: CharacteristicValue) {
266
+ this.platform.debug('blue', "Triggered setConvertibleDrawerMeat");
267
+ if (value === true) {
268
+ const cmdBody = {
269
+ command: {
270
+ commandType: 'cloud.smarthq.command.mode.set',
271
+ mode: this.convertibleDrawerMode.MEAT
272
+ },
273
+ kind: 'service#command',
274
+ deviceId: this.deviceId,
275
+ serviceDeviceType: 'cloud.smarthq.device.refrigerator.convertibledrawer',
276
+ serviceType: 'cloud.smarthq.service.mode',
277
+ domainType: 'cloud.smarthq.domain.mode.selection'
278
+ };
279
+
280
+ const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
281
+
282
+ if (response != null) {
283
+ // Update the switches for Wine, Snacks, Beverages to off
284
+ const switchSnacks = this.accessory.getService("Drawer Snacks");
285
+ switchSnacks?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
286
+ const switchBeverages = this.accessory.getService("Drawer Beverages");
287
+ switchBeverages?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
288
+ const switchWine = this.accessory.getService("Drawer Wine");
289
+ switchWine?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
290
+ }
291
+ }
292
+ }
293
+
294
+ //=====================================================================================
295
+ async setConvertibleDrawerBeverages(value: CharacteristicValue) {
296
+ this.platform.debug('blue', "Triggered setConvertibleDrawerBeverages value: " + value);
297
+
298
+ const cmdBody = {
299
+ command: {
300
+ commandType: 'cloud.smarthq.command.mode.set',
301
+ mode: this.convertibleDrawerMode.BEVERAGES
302
+ },
303
+ kind: 'service#command',
304
+ deviceId: this.deviceId,
305
+ serviceDeviceType: 'cloud.smarthq.device.refrigerator.convertibledrawer',
306
+ serviceType: 'cloud.smarthq.service.mode',
307
+ domainType: 'cloud.smarthq.domain.mode.selection'
308
+ };
309
+
310
+ const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
311
+
312
+ if (response != null) {
313
+ // Update the switches for Wine, Snacks, Meat to off
314
+ const switchSnacks = this.accessory.getService("Drawer Snacks");
315
+ switchSnacks?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
316
+ const switchWine = this.accessory.getService("Drawer Wine");
317
+ switchWine?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
318
+ const switchMeat = this.accessory.getService("Drawer Meat");
319
+ switchMeat?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
320
+ }
321
+ }
322
+
323
+ //=====================================================================================
324
+ async setConvertibleDrawerSnacks(value: CharacteristicValue) {
325
+ this.platform.debug('blue', "Triggered setConvertibleDrawerSnacks value: " + value);
326
+
327
+ const cmdBody = {
328
+ command: {
329
+ commandType: 'cloud.smarthq.command.mode.set',
330
+ mode: this.convertibleDrawerMode.SNACKS
331
+ },
332
+ kind: 'service#command',
333
+ deviceId: this.deviceId,
334
+ serviceDeviceType: 'cloud.smarthq.device.refrigerator.convertibledrawer',
335
+ serviceType: 'cloud.smarthq.service.mode',
336
+ domainType: 'cloud.smarthq.domain.mode.selection'
337
+ };
338
+
339
+ const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
340
+
341
+ if (response != null) {
342
+ // Update the switches for Wine, Meat, Beverages to off
343
+ const switchMeat = this.accessory.getService("Drawer Meat");
344
+ switchMeat?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
345
+ const switchBeverages = this.accessory.getService("Drawer Beverages");
346
+ switchBeverages?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
347
+ const switchWine = this.accessory.getService("Drawer Wine");
348
+ switchWine?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
349
+ }
350
+ }
351
+ //=====================================================================================
352
+ async setConvertibleDrawerWine(value: CharacteristicValue) {
353
+ this.platform.debug('blue', "Triggered setConvertibleDrawerWine value: " + value);
354
+
355
+ const cmdBody = {
356
+ command: {
357
+ commandType: 'cloud.smarthq.command.mode.set',
358
+ mode: this.convertibleDrawerMode.WINE
359
+ },
360
+ kind: 'service#command',
361
+ deviceId: this.deviceId,
362
+ serviceDeviceType: 'cloud.smarthq.device.refrigerator.convertibledrawer',
363
+ serviceType: 'cloud.smarthq.service.mode',
364
+ domainType: 'cloud.smarthq.domain.mode.selection'
365
+ };
366
+
367
+ const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
368
+
369
+ if (response != null) {
370
+ // Update the switches for Meat, Snacks, Beverages to off
371
+ const switchSnacks = this.accessory.getService("Drawer Snacks");
372
+ switchSnacks?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
373
+ const switchBeverages = this.accessory.getService("Drawer Beverages");
374
+ switchBeverages?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
375
+ const switchMeat = this.accessory.getService("Drawer Meat");
376
+ switchMeat?.getCharacteristic(this.platform.Characteristic.On).updateValue(false);
377
+ }
378
+ }
379
+ }
380
+
381
+
@@ -0,0 +1,103 @@
1
+ import { CharacteristicValue, PlatformAccessory, Logging } from 'homebridge';
2
+ import { SmartHqPlatform } from '../platform.js';
3
+ import { SmartHqApi } from '../smartHqApi.js';
4
+ import { DevService } from '../smarthq-types.js';
5
+
6
+ /**
7
+ * Platform Accessory
8
+ * An instance of this class is created for each accessory your platform registers
9
+ * Each accessory may expose multiple services of different service types.
10
+ */
11
+ export class DispenserLight {
12
+ private readonly smartHqApi: SmartHqApi;
13
+ private log : Logging;
14
+
15
+ constructor(
16
+ private readonly platform: SmartHqPlatform,
17
+ private readonly accessory: PlatformAccessory,
18
+ public readonly deviceServices: DevService[],
19
+ public readonly deviceId: string
20
+ ) {
21
+ this.platform = platform;
22
+ this.accessory = accessory;
23
+ this.deviceServices = deviceServices;
24
+ this.deviceId = deviceId;
25
+ this.log = platform.log;
26
+
27
+ this.smartHqApi = new SmartHqApi(this.platform);
28
+ //=====================================================================================
29
+ // Check to see if the device has any supported Convertible Drawer services
30
+ // If not, then don't add services for device that doesn't support it
31
+ //=====================================================================================
32
+
33
+ if (!this.platform.deviceSupportsThisService(this.deviceServices,
34
+ 'cloud.smarthq.device.refrigerator.dispenser.light',
35
+ 'cloud.smarthq.service.toggle',
36
+ 'cloud.smarthq.domain.activate.motion')) {
37
+ this.log.info('No supported Dispenser Light service found for device: ' + this.accessory.displayName);
38
+ return;
39
+ }
40
+ this.platform.debug('green', 'Adding Dispenser Light Switch');
41
+
42
+ //=====================================================================================
43
+ // create a Dispenser Light switch for the Refrigerator
44
+ //=====================================================================================
45
+ const displayName = "Dispenser Light";
46
+
47
+ const dispenserLight = this.accessory.getService(displayName)
48
+ || this.accessory.addService(this.platform.Service.Switch, displayName, 'dispenser-light-123');
49
+ dispenserLight.setCharacteristic(this.platform.Characteristic.Name, displayName);
50
+
51
+ dispenserLight.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
52
+ dispenserLight.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
53
+
54
+ dispenserLight.getCharacteristic(this.platform.Characteristic.On)
55
+ .onGet(this.getdispenserLight.bind(this))
56
+ .onSet(this.setdispenserLight.bind(this));
57
+
58
+ }
59
+
60
+ //=====================================================================================
61
+ async getdispenserLight(): Promise<CharacteristicValue> {
62
+
63
+ let isOn = false;
64
+
65
+ for (const service of this.deviceServices) {
66
+ if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.dispenser.light'
67
+ && service.serviceType === 'cloud.smarthq.service.toggle'
68
+ && service.domainType === 'cloud.smarthq.domain.activate.motion') {
69
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
70
+ if (state?.on == null) {
71
+ this.platform.debug('blue','No On returned from getdispenserLight state');
72
+ return false;
73
+ }
74
+ isOn = state?.on;
75
+ }
76
+ }
77
+ return isOn;
78
+ }
79
+
80
+ //=====================================================================================
81
+ async setdispenserLight(value: CharacteristicValue) {
82
+
83
+ const cmdBody = {
84
+ command: {
85
+ commandType: 'cloud.smarthq.command.toggle.set',
86
+ on: value
87
+ },
88
+ kind: 'service#command',
89
+ deviceId: this.deviceId,
90
+ serviceDeviceType: 'cloud.smarthq.device.refrigerator.dispenser.light',
91
+ serviceType: 'cloud.smarthq.service.toggle',
92
+ domainType: 'cloud.smarthq.domain.activate.motion'
93
+ };
94
+
95
+ const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
96
+
97
+ if (response == null) {
98
+ this.platform.debug('blue', 'No response from setdispenserLight command');
99
+ return;
100
+ }
101
+ this.platform.debug('blue', 'setdispenserLight response: ' + response.outcome);
102
+ }
103
+ }
@@ -0,0 +1,106 @@
1
+ import { CharacteristicValue, PlatformAccessory, Logging } from 'homebridge';
2
+ import { SmartHqPlatform } from '../platform.js';
3
+ import { SmartHqApi } from '../smartHqApi.js';
4
+ import { DevService } from '../smarthq-types.js';
5
+
6
+ /**
7
+ * Platform Accessory
8
+ * An instance of this class is created for each accessory your platform registers
9
+ * Each accessory may expose multiple services of different service types.
10
+ */
11
+ export class EnergySensor {
12
+
13
+ private readonly smartHqApi: SmartHqApi;
14
+ private log : Logging;
15
+ private prevKwhReading: number = 0;
16
+
17
+ constructor(
18
+ private readonly platform: SmartHqPlatform,
19
+ private readonly accessory: PlatformAccessory,
20
+ public readonly deviceServices: DevService[],
21
+ public readonly deviceId: string
22
+ ) {
23
+ this.platform = platform;
24
+ this.accessory = accessory;
25
+ this.deviceServices = deviceServices;
26
+ this.deviceId = deviceId;
27
+ this.log = platform.log;
28
+
29
+ this.smartHqApi = new SmartHqApi(this.platform);
30
+
31
+ //=====================================================================================
32
+ // Check to see if the device has any supported Energy Sensor services
33
+ // If not, then don't add a service for device that doesn't support it
34
+ //=====================================================================================
35
+
36
+ if (!this.platform.deviceSupportsThisService(this.deviceServices,
37
+ 'cloud.smarthq.device.meter',
38
+ 'cloud.smarthq.service.meter',
39
+ 'cloud.smarthq.domain.energy')) {
40
+ this.log.info('No supported Energy Sensor services found for device: ' + this.accessory.displayName);
41
+ return;
42
+ }
43
+ this.platform.debug('green', 'Adding an Energy Sensor');
44
+
45
+ //=====================================================================================
46
+ // create a new water FilterMaintenance service for the Refrigerator
47
+ // This works in Homebridge and HomeKit has a native FilterMaintenance service type but the Home app does not implement it yet
48
+ // so no sensor/accessory will show up in the Home app for this service type.
49
+ //=====================================================================================
50
+ const displayName = "Watts/hr";
51
+ const energySensor = this.accessory.getService(displayName)
52
+ || this.accessory.addService(this.platform.Service.TemperatureSensor, displayName, 'energy-2');
53
+ energySensor.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
54
+ energySensor.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
55
+
56
+ const energyCurrent = energySensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature);
57
+
58
+ //=====================================================================================
59
+ // Now modify the properties for each characteristic to make the temperature sensor
60
+ // function as an energy readout in kWh
61
+ //=====================================================================================
62
+ try {
63
+ energyCurrent.setProps({
64
+ unit: 'kWh',
65
+ minValue: -30.0,
66
+ maxValue: 50000000.0,
67
+ minStep: 1.0
68
+ });
69
+ } catch (error) {
70
+ this.platform.debug('blue', 'Error setting Energy sensor properties: ' + error);
71
+ }
72
+
73
+ //energySensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
74
+ // .onGet(this.getEnergyChange.bind(this));
75
+ //=====================================================================================
76
+ // Poll every 1800 seconds for new energy data
77
+ //=====================================================================================
78
+ setInterval(() => {
79
+ this.getEnergyChange().then(temp => {
80
+ energySensor.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(temp);
81
+ });
82
+ }, 30 * 60 * 1000);
83
+
84
+ }
85
+ //=====================================================================================
86
+ async getEnergyChange(): Promise<CharacteristicValue> {
87
+ let kwhReading = 0
88
+ for (const service of this.deviceServices) {
89
+ if (service.serviceDeviceType === 'cloud.smarthq.device.meter'
90
+ && service.serviceType === 'cloud.smarthq.service.meter') {
91
+
92
+ const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
93
+ if (state?.meterValue == null) {
94
+ this.platform.debug('blue', 'No state.meterValue returned from getEnergyChange state');
95
+ return false;
96
+ }
97
+ kwhReading = state?.meterValue;
98
+ const intervalDelta = kwhReading - this.prevKwhReading;
99
+ kwhReading = (intervalDelta * 2 - 32) / 1.8; // Interval is 30 minutes so double to get hourly rate
100
+ this.prevKwhReading = state?.meterValue;
101
+ break;
102
+ }
103
+ }
104
+ return kwhReading ; // Interval is 30 minutes so double to get hourly rate
105
+ }
106
+ }