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.
- package/LICENSE +21 -0
- package/Readme.md +138 -0
- package/config.schema.json +146 -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 +40 -0
- package/dist/platform.js +243 -0
- package/dist/platform.js.map +1 -0
- package/dist/refrigerator/controlLock.d.ts +19 -0
- package/dist/refrigerator/controlLock.js +85 -0
- package/dist/refrigerator/controlLock.js.map +1 -0
- package/dist/refrigerator/convertibleDrawer.d.ts +27 -0
- package/dist/refrigerator/convertibleDrawer.js +317 -0
- package/dist/refrigerator/convertibleDrawer.js.map +1 -0
- package/dist/refrigerator/dispenserLight.d.ts +19 -0
- package/dist/refrigerator/dispenserLight.js +85 -0
- package/dist/refrigerator/dispenserLight.js.map +1 -0
- package/dist/refrigerator/energy.d.ts +19 -0
- package/dist/refrigerator/energy.js +93 -0
- package/dist/refrigerator/energy.js.map +1 -0
- package/dist/refrigerator/freezer.d.ts +41 -0
- package/dist/refrigerator/freezer.js +188 -0
- package/dist/refrigerator/freezer.js.map +1 -0
- package/dist/refrigerator/iceMaker.d.ts +19 -0
- package/dist/refrigerator/iceMaker.js +81 -0
- package/dist/refrigerator/iceMaker.js.map +1 -0
- package/dist/refrigerator/interiorLight.d.ts +21 -0
- package/dist/refrigerator/interiorLight.js +100 -0
- package/dist/refrigerator/interiorLight.js.map +1 -0
- package/dist/refrigerator/refrigerator.d.ts +41 -0
- package/dist/refrigerator/refrigerator.js +204 -0
- package/dist/refrigerator/refrigerator.js.map +1 -0
- package/dist/refrigerator/refrigeratorAlerts.d.ts +36 -0
- package/dist/refrigerator/refrigeratorAlerts.js +204 -0
- package/dist/refrigerator/refrigeratorAlerts.js.map +1 -0
- package/dist/refrigerator/sabbathMode.d.ts +20 -0
- package/dist/refrigerator/sabbathMode.js +91 -0
- package/dist/refrigerator/sabbathMode.js.map +1 -0
- package/dist/refrigerator/temperatureUnits.d.ts +21 -0
- package/dist/refrigerator/temperatureUnits.js +147 -0
- package/dist/refrigerator/temperatureUnits.js.map +1 -0
- package/dist/refrigerator/turboCoolMode.d.ts +23 -0
- package/dist/refrigerator/turboCoolMode.js +134 -0
- package/dist/refrigerator/turboCoolMode.js.map +1 -0
- package/dist/refrigerator/waterFilter.d.ts +19 -0
- package/dist/refrigerator/waterFilter.js +89 -0
- package/dist/refrigerator/waterFilter.js.map +1 -0
- package/dist/refrigeratorServices.d.ts +5 -0
- package/dist/refrigeratorServices.js +54 -0
- package/dist/refrigeratorServices.js.map +1 -0
- package/dist/settings.d.ts +12 -0
- package/dist/settings.js +13 -0
- package/dist/settings.js.map +1 -0
- package/dist/smartHqApi.d.ts +29 -0
- package/dist/smartHqApi.js +267 -0
- package/dist/smartHqApi.js.map +1 -0
- package/dist/smarthq-types.d.ts +29 -0
- package/dist/smarthq-types.js +2 -0
- package/dist/smarthq-types.js.map +1 -0
- package/eslint.config.js +12 -0
- package/images/homebridge.svg +1 -0
- package/package.json +61 -0
- package/src/@types/homebridge-lib.d.ts +14 -0
- package/src/index.ts +11 -0
- package/src/platform.ts +300 -0
- package/src/refrigerator/controlLock.ts +103 -0
- package/src/refrigerator/convertibleDrawer.ts +381 -0
- package/src/refrigerator/dispenserLight.ts +103 -0
- package/src/refrigerator/energy.ts +106 -0
- package/src/refrigerator/freezer.ts +227 -0
- package/src/refrigerator/iceMaker.ts +100 -0
- package/src/refrigerator/interiorLight.ts +118 -0
- package/src/refrigerator/refrigerator.ts +241 -0
- package/src/refrigerator/refrigeratorAlerts.ts +228 -0
- package/src/refrigerator/sabbathMode.ts +111 -0
- package/src/refrigerator/temperatureUnits.ts +178 -0
- package/src/refrigerator/turboCoolMode.ts +164 -0
- package/src/refrigerator/waterFilter.ts +107 -0
- package/src/refrigeratorServices.ts +60 -0
- package/src/settings.ts +14 -0
- package/src/smartHqApi.ts +305 -0
- package/src/smarthq-types.ts +31 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,227 @@
|
|
|
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 Freezer {
|
|
12
|
+
|
|
13
|
+
// Default temperatures for a GE Profile Refrigerator
|
|
14
|
+
private freezerTargetTemperature = -17.77; // Default 0F
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
private readonly smartHqApi: SmartHqApi;
|
|
18
|
+
private log : Logging;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
private readonly platform: SmartHqPlatform,
|
|
22
|
+
private readonly accessory: PlatformAccessory,
|
|
23
|
+
public readonly deviceServices: DevService[],
|
|
24
|
+
public readonly deviceId: string
|
|
25
|
+
) {
|
|
26
|
+
this.platform = platform;
|
|
27
|
+
this.accessory = accessory;
|
|
28
|
+
this.deviceServices = deviceServices;
|
|
29
|
+
this.deviceId = deviceId;
|
|
30
|
+
this.log = platform.log;
|
|
31
|
+
|
|
32
|
+
this.smartHqApi = new SmartHqApi(this.platform);
|
|
33
|
+
this.platform.debug('green', 'Adding Freezer Thermostat');
|
|
34
|
+
|
|
35
|
+
//=====================================================================================
|
|
36
|
+
// create a new Thermostat service for the Freezer
|
|
37
|
+
//=====================================================================================
|
|
38
|
+
const displayName = "Freezer";
|
|
39
|
+
const freezerThermostat = this.accessory.getService(displayName)
|
|
40
|
+
|| this.accessory.addService(this.platform.Service.Thermostat, displayName, 'freezer-thermo1');
|
|
41
|
+
freezerThermostat.setCharacteristic(this.platform.Characteristic.Name, displayName);
|
|
42
|
+
freezerThermostat.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
|
|
43
|
+
freezerThermostat.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
|
|
44
|
+
|
|
45
|
+
const currentHeatCoolCharacteristicFreezer = freezerThermostat.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState);
|
|
46
|
+
const targetHeatCoolCharacteristicFreezer = freezerThermostat.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState);
|
|
47
|
+
const currentTempCharacteristicFreezer = freezerThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature);
|
|
48
|
+
const targetTempCharacteristicFreezer = freezerThermostat.getCharacteristic(this.platform.Characteristic.TargetTemperature);
|
|
49
|
+
|
|
50
|
+
//=====================================================================================
|
|
51
|
+
// Now modify the properties for each characteristic to match the freezer capabilities
|
|
52
|
+
//=====================================================================================
|
|
53
|
+
currentHeatCoolCharacteristicFreezer.setProps({
|
|
54
|
+
minValue: this.platform.Characteristic.CurrentHeatingCoolingState.OFF,
|
|
55
|
+
maxValue: this.platform.Characteristic.CurrentHeatingCoolingState.COOL,
|
|
56
|
+
validValues: [this.platform.Characteristic.CurrentHeatingCoolingState.COOL]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
targetHeatCoolCharacteristicFreezer.setProps({
|
|
60
|
+
minValue: this.platform.Characteristic.TargetHeatingCoolingState.OFF,
|
|
61
|
+
maxValue: this.platform.Characteristic.TargetHeatingCoolingState.COOL,
|
|
62
|
+
validValues: [this.platform.Characteristic.TargetHeatingCoolingState.COOL]
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
currentTempCharacteristicFreezer.setProps({
|
|
67
|
+
minValue: -21.111, // -6F
|
|
68
|
+
maxValue: -15.0, // 5F
|
|
69
|
+
minStep: 0.1
|
|
70
|
+
});
|
|
71
|
+
} catch (error) {
|
|
72
|
+
this.platform.debug('blue', 'Error setting Freezer Current Temperature properties: ' + error);
|
|
73
|
+
}
|
|
74
|
+
//=====================================================================================
|
|
75
|
+
// Change properties for the characteristic for a GE Profile Refrigerator temperature range is -21.111C (-6F) to -15C (5F)
|
|
76
|
+
// Values obtained from SmartHQ Api service config for refrigerator.freezer.temperature see HB log output when debug is enabled
|
|
77
|
+
//=====================================================================================
|
|
78
|
+
try {
|
|
79
|
+
targetTempCharacteristicFreezer.setProps({
|
|
80
|
+
minValue: -21.111,
|
|
81
|
+
maxValue: -15.0,
|
|
82
|
+
minStep: 0.1
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
this.platform.debug('blue', 'Error setting Freezer Target Temperature properties: ' + error);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// create handlers for required characteristics
|
|
89
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState)
|
|
90
|
+
.onGet(this.getCurrentHeatingCoolingState.bind(this));
|
|
91
|
+
|
|
92
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState)
|
|
93
|
+
.onGet(this.getCurrentHeatingCoolingState.bind(this))
|
|
94
|
+
.onSet(this.setTargetHeatingCoolingState.bind(this));
|
|
95
|
+
|
|
96
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
|
97
|
+
.onGet(this.getFreezerTemperature.bind(this));
|
|
98
|
+
|
|
99
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.TargetTemperature)
|
|
100
|
+
.onGet(this.getFreezerTargetTemperature.bind(this))
|
|
101
|
+
.onSet(this.setFreezerTemperature.bind(this));
|
|
102
|
+
|
|
103
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
|
|
104
|
+
.onGet(this.handleTemperatureDisplayUnitsGet.bind(this))
|
|
105
|
+
.onSet(this.handleTemperatureDisplayUnitsSet.bind(this));
|
|
106
|
+
|
|
107
|
+
//=====================================================================================
|
|
108
|
+
// Updating characteristics values asynchronously.
|
|
109
|
+
//=====================================================================================
|
|
110
|
+
|
|
111
|
+
setInterval(() => {
|
|
112
|
+
// push the new value to HomeKit
|
|
113
|
+
this.getFreezerTemperature().then(temp => {
|
|
114
|
+
freezerThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(temp);
|
|
115
|
+
});
|
|
116
|
+
}, 10000); // every 10 seconds
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
//=====================================================================================
|
|
121
|
+
async getFreezerTemperature(): Promise<CharacteristicValue> {
|
|
122
|
+
let temp = 0;
|
|
123
|
+
for (const service of this.deviceServices) {
|
|
124
|
+
if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.freezer'
|
|
125
|
+
&& service.serviceType === 'cloud.smarthq.service.temperature') {
|
|
126
|
+
|
|
127
|
+
const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
|
|
128
|
+
if (state?.celsiusConverted == null) {
|
|
129
|
+
this.platform.debug('blue', 'No celsiusConverted returned from getFreezerTemperature state');
|
|
130
|
+
return -17.77; // Return -17.77C (0F) if no data
|
|
131
|
+
}
|
|
132
|
+
temp = state?.celsiusConverted;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return temp;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//=====================================================================================
|
|
140
|
+
async setFreezerTemperature(value: CharacteristicValue) {
|
|
141
|
+
this.platform.debug('blue', "Triggered setTemperature");
|
|
142
|
+
|
|
143
|
+
const cmdBody = {
|
|
144
|
+
command: {
|
|
145
|
+
commandType: 'cloud.smarthq.command.temperature.set',
|
|
146
|
+
celsius: value as number
|
|
147
|
+
},
|
|
148
|
+
kind: 'service#command',
|
|
149
|
+
deviceId: this.deviceId,
|
|
150
|
+
serviceDeviceType: 'cloud.smarthq.device.refrigerator.freezer',
|
|
151
|
+
serviceType: 'cloud.smarthq.service.temperature',
|
|
152
|
+
domainType: 'cloud.smarthq.domain.setpoint'
|
|
153
|
+
};
|
|
154
|
+
const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
|
|
155
|
+
|
|
156
|
+
if (response == null) {
|
|
157
|
+
this.platform.debug('blue', 'No response from setFreezerTemperature command');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Handle requests to get the current value of the "Current Heating Cooling State" characteristic
|
|
164
|
+
*/
|
|
165
|
+
//=====================================================================================
|
|
166
|
+
getCurrentHeatingCoolingState() {
|
|
167
|
+
|
|
168
|
+
// set this to a valid value for CurrentHeatingCoolingState
|
|
169
|
+
const currentValue = this.platform.Characteristic.CurrentHeatingCoolingState.COOL;
|
|
170
|
+
|
|
171
|
+
return currentValue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Handle requests to get the current value of the "Target Heating Cooling State" characteristic
|
|
177
|
+
*/
|
|
178
|
+
//=====================================================================================
|
|
179
|
+
setCurrentHeatingCoolingState() {
|
|
180
|
+
|
|
181
|
+
// set this to a valid value for TargetHeatingCoolingState
|
|
182
|
+
const currentValue = this.platform.Characteristic.TargetHeatingCoolingState.COOL;
|
|
183
|
+
|
|
184
|
+
return currentValue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Handle requests to set the "Target Heating Cooling State" characteristic
|
|
189
|
+
*/
|
|
190
|
+
//=====================================================================================
|
|
191
|
+
setTargetHeatingCoolingState(value: CharacteristicValue) {
|
|
192
|
+
// Nothing to do since refrigerator can only be in COOL mode
|
|
193
|
+
|
|
194
|
+
const currentValue = this.platform.Characteristic.TargetHeatingCoolingState.COOL;
|
|
195
|
+
this.platform.debug('blue', 'setTargetHeatingCoolingState value: ' + value + ', returning: ' + currentValue);
|
|
196
|
+
|
|
197
|
+
return currentValue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Handle requests to get the current value of the "Target Temperature" characteristic
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
getFreezerTargetTemperature() {
|
|
205
|
+
const currentValue = this.freezerTargetTemperature
|
|
206
|
+
|
|
207
|
+
return currentValue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
handleTemperatureDisplayUnitsGet() {
|
|
211
|
+
|
|
212
|
+
// set this to a valid value for TemperatureDisplayUnits
|
|
213
|
+
const currentValue = this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
|
|
214
|
+
|
|
215
|
+
return currentValue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Handle requests to set the "Temperature Display Units" characteristic
|
|
220
|
+
*/
|
|
221
|
+
//=====================================================================================
|
|
222
|
+
handleTemperatureDisplayUnitsSet(value: CharacteristicValue) {
|
|
223
|
+
this.platform.debug('blue', 'handleTemperatureDisplayUnitsSet value: ' + value);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
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 IceMaker {
|
|
12
|
+
|
|
13
|
+
private readonly smartHqApi: SmartHqApi;
|
|
14
|
+
private log : Logging;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly platform: SmartHqPlatform,
|
|
18
|
+
private readonly accessory: PlatformAccessory,
|
|
19
|
+
public readonly deviceServices: DevService[],
|
|
20
|
+
public readonly deviceId: string
|
|
21
|
+
) {
|
|
22
|
+
this.platform = platform;
|
|
23
|
+
this.accessory = accessory;
|
|
24
|
+
this.deviceServices = deviceServices;
|
|
25
|
+
this.deviceId = deviceId;
|
|
26
|
+
this.log = platform.log;
|
|
27
|
+
|
|
28
|
+
this.smartHqApi = new SmartHqApi(this.platform);
|
|
29
|
+
|
|
30
|
+
if (!this.platform.deviceSupportsThisService(this.deviceServices,
|
|
31
|
+
'cloud.smarthq.device.icemaker.1',
|
|
32
|
+
'cloud.smarthq.service.toggle',
|
|
33
|
+
'cloud.smarthq.domain.power')) {
|
|
34
|
+
this.log.info('No supported Ice Maker service found for device: ' + this.accessory.displayName);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.platform.debug('green', 'Adding Ice Maker Switch');
|
|
38
|
+
|
|
39
|
+
//=====================================================================================
|
|
40
|
+
// create a Ice Maker switch for the Refrigerator
|
|
41
|
+
//=====================================================================================
|
|
42
|
+
const displayName = "Ice Maker";
|
|
43
|
+
|
|
44
|
+
const iceMaker = this.accessory.getService(displayName)
|
|
45
|
+
|| this.accessory.addService(this.platform.Service.Switch, displayName, 'ice-maker-123');
|
|
46
|
+
iceMaker.setCharacteristic(this.platform.Characteristic.Name, displayName);
|
|
47
|
+
|
|
48
|
+
iceMaker.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
|
|
49
|
+
iceMaker.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
|
|
50
|
+
|
|
51
|
+
iceMaker.getCharacteristic(this.platform.Characteristic.On)
|
|
52
|
+
.onGet(this.geticeMaker.bind(this))
|
|
53
|
+
.onSet(this.seticeMaker.bind(this));
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//=====================================================================================
|
|
58
|
+
async geticeMaker(): Promise<CharacteristicValue> {
|
|
59
|
+
|
|
60
|
+
let isOn = false;
|
|
61
|
+
|
|
62
|
+
for (const service of this.deviceServices) {
|
|
63
|
+
if (service.serviceDeviceType === 'cloud.smarthq.device.icemaker.1'
|
|
64
|
+
&& service.serviceType === 'cloud.smarthq.service.toggle'
|
|
65
|
+
&& service.domainType === 'cloud.smarthq.domain.power') {
|
|
66
|
+
const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
|
|
67
|
+
if (state?.on == null) {
|
|
68
|
+
this.platform.debug('blue', 'No state.On returned from geticeMaker state');
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
isOn = state?.on;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return isOn;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//=====================================================================================
|
|
78
|
+
async seticeMaker(value: CharacteristicValue) {
|
|
79
|
+
this.platform.debug('blue', "Triggered seticeMaker toggle");
|
|
80
|
+
|
|
81
|
+
const cmdBody = {
|
|
82
|
+
command: {
|
|
83
|
+
commandType: 'cloud.smarthq.command.toggle.set',
|
|
84
|
+
on: value
|
|
85
|
+
},
|
|
86
|
+
kind: 'service#command',
|
|
87
|
+
deviceId: this.deviceId,
|
|
88
|
+
serviceDeviceType: 'cloud.smarthq.device.icemaker.1',
|
|
89
|
+
serviceType: 'cloud.smarthq.service.toggle',
|
|
90
|
+
domainType: 'cloud.smarthq.domain.power'
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
|
|
94
|
+
|
|
95
|
+
if (response == null) {
|
|
96
|
+
this.platform.debug('blue', 'No response from seticeMaker command');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
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 InteriorLight {
|
|
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
|
+
if (!this.platform.deviceSupportsThisService(this.deviceServices,
|
|
30
|
+
'cloud.smarthq.device.refrigerator',
|
|
31
|
+
'cloud.smarthq.service.integer',
|
|
32
|
+
'cloud.smarthq.domain.brightness.light')) {
|
|
33
|
+
this.log.info('No supported Interior Light service found for device: ' + this.accessory.displayName);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.platform.debug('green', 'Adding Interior Light Switch');
|
|
37
|
+
// set accessory information
|
|
38
|
+
|
|
39
|
+
//=====================================================================================
|
|
40
|
+
// create a new Lightbulb service for the Refrigerator Wall Brightness Light
|
|
41
|
+
//=====================================================================================
|
|
42
|
+
const displayName = "Fridge Light";
|
|
43
|
+
const refrigeratorLight = this.accessory.getService(displayName)
|
|
44
|
+
|| this.accessory.addService(this.platform.Service.Lightbulb, displayName, 'brightness-light-2');
|
|
45
|
+
|
|
46
|
+
refrigeratorLight.setCharacteristic(this.platform.Characteristic.Name, displayName);
|
|
47
|
+
refrigeratorLight.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
|
|
48
|
+
refrigeratorLight.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
|
|
49
|
+
|
|
50
|
+
refrigeratorLight.getCharacteristic(this.platform.Characteristic.On).updateValue(true);
|
|
51
|
+
refrigeratorLight.getCharacteristic(this.platform.Characteristic.On)
|
|
52
|
+
.onGet(this.getRefrigBrightnessLightOn.bind(this))
|
|
53
|
+
.onSet(this.setRefrigBrightnessLightOn.bind(this));
|
|
54
|
+
|
|
55
|
+
refrigeratorLight.getCharacteristic(this.platform.Characteristic.Brightness)
|
|
56
|
+
.onGet(this.getFridgeBackLight.bind(this))
|
|
57
|
+
.onSet(this.setFridgeBackLight.bind(this));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
//=====================================================================================
|
|
62
|
+
async getFridgeBackLight(): Promise<CharacteristicValue> {
|
|
63
|
+
let brightness = 0;
|
|
64
|
+
for (const service of this.deviceServices) {
|
|
65
|
+
if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator'
|
|
66
|
+
&& service.serviceType === 'cloud.smarthq.service.integer') {
|
|
67
|
+
|
|
68
|
+
const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
|
|
69
|
+
if (state?.value == null) {
|
|
70
|
+
this.platform.debug('blue', 'No state.value returned from getFridgeBackLight state');
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
brightness = state?.value;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return brightness;
|
|
78
|
+
}
|
|
79
|
+
//=====================================================================================
|
|
80
|
+
// Set handler for Brightness characteristics for Lightbulb service
|
|
81
|
+
//=====================================================================================
|
|
82
|
+
async setFridgeBackLight(value: CharacteristicValue) {
|
|
83
|
+
|
|
84
|
+
const cmdBody = {
|
|
85
|
+
command: {
|
|
86
|
+
commandType: 'cloud.smarthq.command.integer.set',
|
|
87
|
+
value: value as number
|
|
88
|
+
},
|
|
89
|
+
kind: 'service#command',
|
|
90
|
+
deviceId: this.deviceId,
|
|
91
|
+
serviceDeviceType: 'cloud.smarthq.device.refrigerator',
|
|
92
|
+
serviceType: 'cloud.smarthq.service.integer',
|
|
93
|
+
domainType: 'cloud.smarthq.domain.brightness.light'
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
|
|
97
|
+
|
|
98
|
+
if (response == null) {
|
|
99
|
+
this.platform.debug('blue', 'No response from setFridgeBackLight command');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
//=====================================================================================
|
|
105
|
+
async getRefrigBrightnessLightOn() {
|
|
106
|
+
// SmartHQ API does not have an On/Off command for the refrigerator brightness light only brightness level 0-100
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//=====================================================================================
|
|
111
|
+
async setRefrigBrightnessLightOn(value: CharacteristicValue) {
|
|
112
|
+
// SmartHQ API does not have an On/Off command for the refrigerator brightness light only brightness level 0-100
|
|
113
|
+
if (value === false) {
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
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 Refrigerator {
|
|
12
|
+
// Default temperatures for a GE Profile Refrigerator
|
|
13
|
+
private refrigeratorTargetTemperature = 2.78; // Default 37F in Celsius
|
|
14
|
+
|
|
15
|
+
private readonly smartHqApi: SmartHqApi;
|
|
16
|
+
private log : Logging;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
private readonly platform: SmartHqPlatform,
|
|
20
|
+
private readonly accessory: PlatformAccessory,
|
|
21
|
+
public readonly deviceServices: DevService[],
|
|
22
|
+
public readonly deviceId: string
|
|
23
|
+
) {
|
|
24
|
+
this.platform = platform;
|
|
25
|
+
this.accessory = accessory;
|
|
26
|
+
this.deviceServices = deviceServices;
|
|
27
|
+
this.deviceId = deviceId;
|
|
28
|
+
this.log = platform.log;
|
|
29
|
+
|
|
30
|
+
this.smartHqApi = new SmartHqApi(this.platform);
|
|
31
|
+
|
|
32
|
+
this.platform.debug('green', 'Adding Refrigerator Thermostat');
|
|
33
|
+
|
|
34
|
+
// set accessory information
|
|
35
|
+
this.accessory.getService(this.platform.Service.AccessoryInformation)!
|
|
36
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'GE')
|
|
37
|
+
.setCharacteristic(this.platform.Characteristic.Model, accessory.context.device.model || 'Default-Model')
|
|
38
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.context.device.serial || 'Default-Serial');
|
|
39
|
+
|
|
40
|
+
//=====================================================================================
|
|
41
|
+
// create a new Thermostat service for the Refrigerator
|
|
42
|
+
//=====================================================================================
|
|
43
|
+
const displayName = "Refrigerator";
|
|
44
|
+
const refrigeratorThermostat = this.accessory.getService(displayName)
|
|
45
|
+
|| this.accessory.addService(this.platform.Service.Thermostat, displayName, 'fridge-thermo1');
|
|
46
|
+
// set the service name, this is what is displayed as the default name on the Home app
|
|
47
|
+
refrigeratorThermostat.setCharacteristic(this.platform.Characteristic.Name, displayName);
|
|
48
|
+
refrigeratorThermostat.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName)
|
|
49
|
+
refrigeratorThermostat.setCharacteristic(this.platform.Characteristic.ConfiguredName, displayName)
|
|
50
|
+
|
|
51
|
+
const currentHeatCoolCharacteristic = refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState);
|
|
52
|
+
const targetHeatCoolCharacteristic = refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState);
|
|
53
|
+
const currentTempCharacteristic = refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature);
|
|
54
|
+
const targetTempCharacteristic = refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.TargetTemperature);
|
|
55
|
+
|
|
56
|
+
// Now modify the properties for each characteristic to match the refrigerator capabilities
|
|
57
|
+
// Only allow COOL mode for refrigerator
|
|
58
|
+
currentHeatCoolCharacteristic.setProps({
|
|
59
|
+
minValue: this.platform.Characteristic.CurrentHeatingCoolingState.OFF,
|
|
60
|
+
maxValue: this.platform.Characteristic.CurrentHeatingCoolingState.COOL,
|
|
61
|
+
validValues: [this.platform.Characteristic.CurrentHeatingCoolingState.COOL]
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Only allow COOL mode for refrigerator
|
|
65
|
+
targetHeatCoolCharacteristic.setProps({
|
|
66
|
+
minValue: this.platform.Characteristic.TargetHeatingCoolingState.OFF,
|
|
67
|
+
maxValue: this.platform.Characteristic.TargetHeatingCoolingState.COOL,
|
|
68
|
+
validValues: [this.platform.Characteristic.TargetHeatingCoolingState.COOL]
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
currentTempCharacteristic.setProps({
|
|
73
|
+
minValue: 0,
|
|
74
|
+
maxValue: 8.0,
|
|
75
|
+
minStep: 0.1
|
|
76
|
+
});
|
|
77
|
+
} catch (error) {
|
|
78
|
+
this.platform.debug('blue', 'Error setting Refrigerator Current Temperature properties: ' + error);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Change properties for the characteristic for a GE Profile Refrigerator temperature range is 1.111C (34F) to 5.556C (42F)
|
|
82
|
+
// Values obtained from SmartHQ Api service config for refrigerator.freshfood.temperature see HB log output when debug is enabled
|
|
83
|
+
try {
|
|
84
|
+
targetTempCharacteristic.setProps({
|
|
85
|
+
minValue: 1.111,
|
|
86
|
+
maxValue: 5.556,
|
|
87
|
+
minStep: 0.1
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
this.platform.debug('blue', 'Error setting Refrigerator Target Temperature properties: ' + error);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// create handlers for required characteristics
|
|
94
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState)
|
|
95
|
+
.onGet(this.getCurrentHeatingCoolingState.bind(this));
|
|
96
|
+
// Only allow COOL mode for refrigerator
|
|
97
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState)
|
|
98
|
+
.onGet(this.setTargetHeatingCoolingState.bind(this))
|
|
99
|
+
.onSet(this.setTargetHeatingCoolingState.bind(this));
|
|
100
|
+
|
|
101
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
|
102
|
+
.onGet(this.getFridgeTemperature.bind(this));
|
|
103
|
+
|
|
104
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.TargetTemperature)
|
|
105
|
+
.onGet(this.getFridgeTemperature.bind(this))
|
|
106
|
+
.onSet(this.setFridgeTemperature.bind(this));
|
|
107
|
+
|
|
108
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
|
|
109
|
+
.onGet(this.handleTemperatureDisplayUnitsGet.bind(this))
|
|
110
|
+
.onSet(this.handleTemperatureDisplayUnitsSet.bind(this));
|
|
111
|
+
|
|
112
|
+
//=====================================================================================
|
|
113
|
+
// Updating characteristics values asynchronously.
|
|
114
|
+
//=====================================================================================
|
|
115
|
+
|
|
116
|
+
setInterval(() => {
|
|
117
|
+
// push the new value to HomeKit
|
|
118
|
+
this.getFridgeTemperature().then(temp => {
|
|
119
|
+
refrigeratorThermostat.getCharacteristic(this.platform.Characteristic.CurrentTemperature).updateValue(temp);
|
|
120
|
+
});
|
|
121
|
+
}, 5000);
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//=====================================================================================
|
|
126
|
+
// Refrigerator Temperature Handlers using SmartHQ API commands in smartHqApi.ts
|
|
127
|
+
//=====================================================================================
|
|
128
|
+
async getFridgeTemperature(): Promise<CharacteristicValue> {
|
|
129
|
+
let temp = 0;
|
|
130
|
+
for (const service of this.deviceServices) {
|
|
131
|
+
if (service.serviceDeviceType === 'cloud.smarthq.device.refrigerator.freshfood'
|
|
132
|
+
&& service.serviceType === 'cloud.smarthq.service.temperature') {
|
|
133
|
+
|
|
134
|
+
const state = await this.smartHqApi.getServiceState(this.deviceId, service.serviceId);
|
|
135
|
+
if (state?.celsiusConverted == null) {
|
|
136
|
+
this.platform.debug('blue', 'No state.celsiusConverted returned from getFridgeTemperature state');
|
|
137
|
+
return 2.78; // Return 2.78C (37F) if no data
|
|
138
|
+
}
|
|
139
|
+
temp = state?.celsiusConverted;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// if you need to return an error to show the device as "Not Responding" in the Home app:
|
|
145
|
+
// throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
146
|
+
|
|
147
|
+
return temp;
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
//=====================================================================================
|
|
153
|
+
async setFridgeTemperature(value: CharacteristicValue) {
|
|
154
|
+
if (this.platform.config.debug) {
|
|
155
|
+
this.log.info("Triggered setTemperature");
|
|
156
|
+
}
|
|
157
|
+
this.refrigeratorTargetTemperature = value as number;
|
|
158
|
+
|
|
159
|
+
const cmdBody = {
|
|
160
|
+
command: {
|
|
161
|
+
commandType: 'cloud.smarthq.command.temperature.set',
|
|
162
|
+
celsius: value as number
|
|
163
|
+
},
|
|
164
|
+
kind: 'service#command',
|
|
165
|
+
deviceId: this.deviceId,
|
|
166
|
+
serviceDeviceType: 'cloud.smarthq.device.refrigerator.freshfood',
|
|
167
|
+
serviceType: 'cloud.smarthq.service.temperature',
|
|
168
|
+
domainType: 'cloud.smarthq.domain.setpoint'
|
|
169
|
+
};
|
|
170
|
+
const response = await this.smartHqApi.command(JSON.stringify(cmdBody));
|
|
171
|
+
|
|
172
|
+
if (response == null) {
|
|
173
|
+
this.platform.debug('blue', 'No response from setFridgeTemperature command');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
//=====================================================================================
|
|
180
|
+
getCurrentHeatingCoolingState() {
|
|
181
|
+
|
|
182
|
+
// set this to a valid value for CurrentHeatingCoolingState
|
|
183
|
+
const currentValue = this.platform.Characteristic.CurrentHeatingCoolingState.COOL;
|
|
184
|
+
|
|
185
|
+
return currentValue;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Handle requests to get the current value of the "Target Heating Cooling State" characteristic
|
|
189
|
+
*/
|
|
190
|
+
//=====================================================================================
|
|
191
|
+
setCurrentHeatingCoolingState() {
|
|
192
|
+
|
|
193
|
+
// set this to a valid value for TargetHeatingCoolingState
|
|
194
|
+
const currentValue = this.platform.Characteristic.TargetHeatingCoolingState.COOL;
|
|
195
|
+
|
|
196
|
+
return currentValue;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Handle requests to set the "Target Heating Cooling State" characteristic
|
|
200
|
+
*/
|
|
201
|
+
//=====================================================================================
|
|
202
|
+
setTargetHeatingCoolingState(value: CharacteristicValue) {
|
|
203
|
+
// Nothing to do since refrigerator can only be in COOL mode
|
|
204
|
+
this.platform.debug('green', 'setTargetHeatingCoolingState called with value: ' + value);
|
|
205
|
+
const currentValue = this.platform.Characteristic.TargetHeatingCoolingState.COOL;
|
|
206
|
+
|
|
207
|
+
return currentValue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Handle requests to get the current value of the "Target Temperature" characteristic
|
|
212
|
+
*/
|
|
213
|
+
//=====================================================================================
|
|
214
|
+
getTargetTemperatureGet() {
|
|
215
|
+
const currentValue = this.refrigeratorTargetTemperature
|
|
216
|
+
|
|
217
|
+
return currentValue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Handle requests to get the current value of the "Temperature Display Units" characteristic
|
|
222
|
+
*/
|
|
223
|
+
//=====================================================================================
|
|
224
|
+
handleTemperatureDisplayUnitsGet() {
|
|
225
|
+
|
|
226
|
+
// set this to a valid value for TemperatureDisplayUnits
|
|
227
|
+
const currentValue = this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
|
|
228
|
+
|
|
229
|
+
return currentValue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handle requests to set the "Temperature Display Units" characteristic
|
|
234
|
+
*/
|
|
235
|
+
//=====================================================================================
|
|
236
|
+
handleTemperatureDisplayUnitsSet(value: CharacteristicValue) {
|
|
237
|
+
if (value === this.platform.Characteristic.TemperatureDisplayUnits.FAHRENHEIT) {
|
|
238
|
+
this.platform.debug('green', 'Temperature Display Units set to FAHRENHEIT');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|