homebridge-smarthq-client 1.2.5-debug.9 → 1.2.5-test.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.
@@ -1,5 +1,5 @@
1
1
  import { PlatformAccessory, Service, Characteristic } from 'homebridge';
2
- import { DeviceService, SendCommandRequest } from 'ge-smarthq-api';
2
+ import { DeviceService } from 'ge-smarthq-api';
3
3
  import { SmartHqPlatform } from '../platform.js';
4
4
  export declare class AirConditioner {
5
5
  private readonly platform;
@@ -8,7 +8,7 @@ export declare class AirConditioner {
8
8
  private readonly deviceId;
9
9
  private readonly groupAccessory;
10
10
  private lastActiveMode;
11
- private lastActiveFanSpeedMode;
11
+ private lastActiveFanSpeed;
12
12
  private lastActiveCelsius;
13
13
  private isOn;
14
14
  private physicalOnState;
@@ -17,20 +17,6 @@ export declare class AirConditioner {
17
17
  private currentAmbientCelsius;
18
18
  private coolCelsiusMin;
19
19
  private coolCelsiusMax;
20
- private readonly MODE_COOL;
21
- private readonly MODE_FANONLY;
22
- private readonly MODE_DRY;
23
- private readonly MODE_ENERGY_SAVER;
24
- private readonly MODE_COOL_QUIET;
25
- private readonly MODE_COOL_TURBO;
26
- private readonly MODE_HEAT;
27
- private readonly MODE_OFF;
28
- private readonly MODE_ON;
29
- private readonly FAN_SPEED_LOW;
30
- private readonly FAN_SPEED_MEDIUM;
31
- private readonly FAN_SPEED_HIGH;
32
- private readonly FAN_SPEED_AUTO;
33
- private readonly FAN_SPEED_OFF;
34
20
  private client;
35
21
  private api;
36
22
  Service: typeof Service;
@@ -44,11 +30,10 @@ export declare class AirConditioner {
44
30
  constructor(platform: SmartHqPlatform, accessory: PlatformAccessory, // Parent: Air Conditioner
45
31
  deviceServices: DeviceService[], deviceId: string, groupAccessory: PlatformAccessory[]);
46
32
  private setupAccessories;
47
- sendCommand(cmdBody: SendCommandRequest): Promise<boolean | undefined>;
33
+ private sendCommand;
34
+ private executeSendCommand;
48
35
  private handleUpdate;
49
36
  private findService;
50
37
  private getLastElementAndCapitalize;
51
38
  private setupWebSocket;
52
- private addDebugState;
53
- setupService(serviceType: string, displayName: string, serviceIdSuffix: string): Service;
54
39
  }
@@ -1,5 +1,4 @@
1
1
  import { SmartHQClient } from 'ge-smarthq-api';
2
- import chalk from 'chalk';
3
2
  export class AirConditioner {
4
3
  platform;
5
4
  accessory;
@@ -8,7 +7,7 @@ export class AirConditioner {
8
7
  groupAccessory;
9
8
  // State cache
10
9
  lastActiveMode = 'cloud.smarthq.type.thermostatmode.cool';
11
- lastActiveFanSpeedMode = 'cloud.smarthq.type.fanspeed.low';
10
+ lastActiveFanSpeed = 'cloud.smarthq.type.fanspeed.low';
12
11
  lastActiveCelsius = 22.22;
13
12
  isOn = false;
14
13
  physicalOnState = false;
@@ -18,22 +17,6 @@ export class AirConditioner {
18
17
  // Configuration thresholds
19
18
  coolCelsiusMin = 17.77;
20
19
  coolCelsiusMax = 30.0;
21
- //======== Thermostat mode constants ========
22
- MODE_COOL = "cloud.smarthq.type.thermostatmode.cool";
23
- MODE_FANONLY = "cloud.smarthq.type.thermostatmode.fanonly";
24
- MODE_DRY = "cloud.smarthq.type.thermostatmode.dry";
25
- MODE_ENERGY_SAVER = "cloud.smarthq.type.thermostatmode.cool.energysaver";
26
- MODE_COOL_QUIET = "cloud.smarthq.type.thermostatmode.cool.quiet";
27
- MODE_COOL_TURBO = "cloud.smarthq.type.thermostatmode.cool.turbo";
28
- MODE_HEAT = "cloud.smarthq.type.thermostatmode.heat";
29
- MODE_OFF = "cloud.smarthq.type.thermostatmode.off";
30
- MODE_ON = "cloud.smarthq.type.thermostatmode.on";
31
- //======== Fan speed constants ========
32
- FAN_SPEED_LOW = "cloud.smarthq.type.fanspeed.low";
33
- FAN_SPEED_MEDIUM = "cloud.smarthq.type.fanspeed.medium";
34
- FAN_SPEED_HIGH = "cloud.smarthq.type.fanspeed.high";
35
- FAN_SPEED_AUTO = "cloud.smarthq.type.fanspeed.auto";
36
- FAN_SPEED_OFF = "cloud.smarthq.type.fanspeed.off";
37
20
  client;
38
21
  api;
39
22
  Service;
@@ -79,7 +62,7 @@ export class AirConditioner {
79
62
  this.lastActiveMode = thermostatService.state.mode;
80
63
  }
81
64
  if (thermostatService.state.fanSpeed != null) {
82
- this.lastActiveFanSpeedMode = thermostatService.state.fanSpeed;
65
+ this.lastActiveFanSpeed = thermostatService.state.fanSpeed;
83
66
  }
84
67
  }
85
68
  // Load Celsius min/max bounds from thermostat config
@@ -145,31 +128,14 @@ export class AirConditioner {
145
128
  .onSet(async (value) => {
146
129
  this.isOn = value === 1;
147
130
  if (this.isOn) {
148
- const stateVal = this.lastActiveMode === this.MODE_FANONLY ? 1 : 3;
131
+ const stateVal = this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' ? 1 : 3;
149
132
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, stateVal);
150
133
  for (const [mode, service] of this.modeOutlets.entries()) {
151
134
  service.updateCharacteristic(this.Characteristic.On, this.lastActiveMode === mode);
152
135
  }
153
136
  for (const [fanSpeed, service] of this.fanOutlets.entries()) {
154
- service.updateCharacteristic(this.Characteristic.On, this.lastActiveFanSpeedMode === fanSpeed);
137
+ service.updateCharacteristic(this.Characteristic.On, this.lastActiveFanSpeed === fanSpeed);
155
138
  }
156
- // Turned on, so set mode, fan speed and temperature to last active values. Default to Cool and Low and 22.22C if no last active values.
157
- const cmdBody = {
158
- command: {
159
- mode: this.lastActiveMode || this.MODE_COOL,
160
- fanSpeed: this.lastActiveFanSpeedMode || this.FAN_SPEED_LOW,
161
- temperature: this.lastActiveCelsius || 22.22,
162
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
163
- },
164
- kind: 'service#command',
165
- deviceId: this.deviceId,
166
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
167
- serviceType: 'cloud.smarthq.service.thermostat.v1',
168
- domainType: 'cloud.smarthq.domain.thermostat',
169
- };
170
- this.client.debug(chalk.yellow(`## Turning on AC:`));
171
- this.client.debug(chalk.yellow(JSON.stringify(cmdBody, null, 2)));
172
- this.sendCommand(cmdBody);
173
139
  }
174
140
  else {
175
141
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, 0);
@@ -179,29 +145,15 @@ export class AirConditioner {
179
145
  for (const service of this.fanOutlets.values()) {
180
146
  service.updateCharacteristic(this.Characteristic.On, false);
181
147
  }
182
- // Turned off, so send command to power down AC unit. Note: GE firmware does not support a "power off" command, so we just send the "on" parameter as false to turn off the unit.
183
- const cmdBody = {
184
- command: {
185
- on: this.isOn,
186
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
187
- },
188
- kind: 'service#command',
189
- deviceId: this.deviceId,
190
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
191
- serviceType: 'cloud.smarthq.service.thermostat.v1',
192
- domainType: 'cloud.smarthq.domain.thermostat',
193
- };
194
- this.client.debug(chalk.yellow(`## Turning off AC:`));
195
- this.client.debug(chalk.yellow(JSON.stringify(cmdBody, null, 2)));
196
- this.sendCommand(cmdBody);
197
148
  }
149
+ this.sendCommand();
198
150
  });
199
151
  this.acThermostat
200
152
  .getCharacteristic(this.Characteristic.CurrentHeaterCoolerState)
201
153
  .onGet(() => {
202
154
  if (!this.isOn)
203
155
  return 0;
204
- return this.lastActiveMode === this.MODE_FANONLY ? 1 : 3;
156
+ return this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' ? 1 : 3;
205
157
  });
206
158
  this.acThermostat
207
159
  .getCharacteristic(this.Characteristic.TargetHeaterCoolerState)
@@ -220,24 +172,7 @@ export class AirConditioner {
220
172
  .onGet(() => this.lastActiveCelsius)
221
173
  .onSet(async (value) => {
222
174
  this.lastActiveCelsius = value;
223
- // Clip celsius to hardware bounds to prevent API errors
224
- const clippedCelsius = Math.max(this.coolCelsiusMin, Math.min(this.coolCelsiusMax, this.lastActiveCelsius));
225
- const coolFahrenheit = Math.round(clippedCelsius * 1.8 + 32);
226
- // Set temperature on the AC unit via API command
227
- const cmdBody = {
228
- command: {
229
- coolFahrenheit: coolFahrenheit,
230
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
231
- },
232
- kind: 'service#command',
233
- deviceId: this.deviceId,
234
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
235
- serviceType: 'cloud.smarthq.service.thermostat.v1',
236
- domainType: 'cloud.smarthq.domain.thermostat',
237
- };
238
- this.client.debug(chalk.yellow('## Setting AC Temperature:'));
239
- this.client.debug(chalk.yellow(JSON.stringify(cmdBody, null, 2)));
240
- this.sendCommand(cmdBody);
175
+ this.sendCommand();
241
176
  });
242
177
  this.acThermostat
243
178
  .getCharacteristic(this.Characteristic.CurrentTemperature)
@@ -291,61 +226,12 @@ export class AirConditioner {
291
226
  }
292
227
  }
293
228
  this.acThermostat.updateCharacteristic(this.Characteristic.Active, 1);
294
- const stateVal = mode === this.MODE_FANONLY ? 1 : 3;
229
+ const stateVal = mode === 'cloud.smarthq.type.thermostatmode.fanonly' ? 1 : 3;
295
230
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, stateVal);
296
- for (const [fanspeedMode, service] of this.fanOutlets.entries()) {
297
- service.updateCharacteristic(this.Characteristic.On, this.lastActiveFanSpeedMode === fanspeedMode);
298
- }
299
- // Handle behavior constraint: Fan Only mode does not support Auto Fan Speed - force Fan Speed to Low
300
- // Dry mode sets fan speed to Auto, which is valid. Only Fan Only mode needs to be adjusted.
301
- let cmdBody;
302
- switch (mode) {
303
- case this.MODE_FANONLY:
304
- cmdBody = {
305
- command: {
306
- mode: this.MODE_FANONLY,
307
- fanSpeed: this.FAN_SPEED_LOW,
308
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
309
- },
310
- kind: 'service#command',
311
- deviceId: this.deviceId,
312
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
313
- serviceType: 'cloud.smarthq.service.thermostat.v1',
314
- domainType: 'cloud.smarthq.domain.thermostat',
315
- };
316
- break;
317
- case this.MODE_DRY:
318
- cmdBody = {
319
- command: {
320
- mode: this.MODE_DRY,
321
- // fanSpeed: this.FAN_SPEED_AUTO, set to Auto by default for Dry mode, which is valid
322
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
323
- },
324
- kind: 'service#command',
325
- deviceId: this.deviceId,
326
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
327
- serviceType: 'cloud.smarthq.service.thermostat.v1',
328
- domainType: 'cloud.smarthq.domain.thermostat',
329
- };
330
- break;
331
- // Default case handles Cool and Heat modes, which support all(?) fan speeds
332
- default:
333
- // Set mode on the AC unit via API command with special handling for Fan Only and Dry modes
334
- cmdBody = {
335
- command: {
336
- mode: mode,
337
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
338
- },
339
- kind: 'service#command',
340
- deviceId: this.deviceId,
341
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
342
- serviceType: 'cloud.smarthq.service.thermostat.v1',
343
- domainType: 'cloud.smarthq.domain.thermostat',
344
- };
231
+ for (const [fanSpeed, service] of this.fanOutlets.entries()) {
232
+ service.updateCharacteristic(this.Characteristic.On, this.lastActiveFanSpeed === fanSpeed);
345
233
  }
346
- this.client.debug(chalk.yellow('## Setting AC Mode:'));
347
- this.client.debug(chalk.yellow(JSON.stringify(cmdBody, null, 2)));
348
- this.sendCommand(cmdBody);
234
+ this.sendCommand();
349
235
  }
350
236
  else {
351
237
  // Toggling active mode OFF powers down system
@@ -359,18 +245,7 @@ export class AirConditioner {
359
245
  }
360
246
  this.acThermostat.updateCharacteristic(this.Characteristic.Active, 0);
361
247
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, 0);
362
- const cmdBody = {
363
- command: {
364
- on: this.isOn,
365
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
366
- },
367
- kind: 'service#command',
368
- deviceId: this.deviceId,
369
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
370
- serviceType: 'cloud.smarthq.service.thermostat.v1',
371
- domainType: 'cloud.smarthq.domain.thermostat',
372
- };
373
- this.sendCommand(cmdBody);
248
+ this.sendCommand();
374
249
  }
375
250
  }
376
251
  });
@@ -385,16 +260,16 @@ export class AirConditioner {
385
260
  .setCharacteristic(this.Characteristic.SerialNumber, this.parentAccessory.context.device.serial || 'Unknown');
386
261
  // Clean up stale Fan Speed outlets from cache
387
262
  const activeFanServiceUUIDs = new Set();
388
- for (const fanspeedMode of supportedFanSpeeds) {
389
- const [displayName] = this.getLastElementAndCapitalize(fanspeedMode, '.');
263
+ for (const speed of supportedFanSpeeds) {
264
+ const [displayName] = this.getLastElementAndCapitalize(speed, '.');
390
265
  const service = this.fanAccessory.getService(displayName) ||
391
- this.fanAccessory.addService(this.Service.Outlet, displayName, fanspeedMode);
266
+ this.fanAccessory.addService(this.Service.Outlet, displayName, speed);
392
267
  if (!service.getCharacteristic(this.Characteristic.ConfiguredName)) {
393
268
  service.addOptionalCharacteristic(this.Characteristic.ConfiguredName);
394
269
  }
395
270
  service.setCharacteristic(this.Characteristic.Name, displayName);
396
271
  service.setCharacteristic(this.Characteristic.ConfiguredName, displayName);
397
- activeFanServiceUUIDs.add(service.UUID + (fanspeedMode || ''));
272
+ activeFanServiceUUIDs.add(service.UUID + (speed || ''));
398
273
  }
399
274
  for (const service of [...this.fanAccessory.services]) {
400
275
  if (service.UUID === this.Service.AccessoryInformation.UUID)
@@ -408,25 +283,21 @@ export class AirConditioner {
408
283
  }
409
284
  }
410
285
  // Bind Fan Speed Outlets characteristics
411
- for (const fanspeedMode of supportedFanSpeeds) {
412
- const [displayName] = this.getLastElementAndCapitalize(fanspeedMode, '.');
286
+ for (const speed of supportedFanSpeeds) {
287
+ const [displayName] = this.getLastElementAndCapitalize(speed, '.');
413
288
  const service = this.fanAccessory.getService(displayName);
414
- this.fanOutlets.set(fanspeedMode, service);
289
+ this.fanOutlets.set(speed, service);
415
290
  service
416
291
  .getCharacteristic(this.Characteristic.On)
417
- .onGet(() => this.isOn && this.lastActiveFanSpeedMode === fanspeedMode)
292
+ .onGet(() => this.isOn && this.lastActiveFanSpeed === speed)
418
293
  .onSet(async (value) => {
419
294
  if (value) {
420
- // If mode is Dry, then fan speed is automatically set to Auto and cannot be changed.
421
- if (this.lastActiveMode === this.MODE_DRY) {
422
- return;
423
- }
424
295
  // Handle behavior constraint: Fan Only mode does not support Auto Fan Speed
425
- if (this.lastActiveMode === this.MODE_FANONLY &&
426
- fanspeedMode === this.FAN_SPEED_AUTO) {
296
+ if (this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' &&
297
+ speed === 'cloud.smarthq.type.fanspeed.auto') {
427
298
  setTimeout(() => {
428
299
  service.updateCharacteristic(this.Characteristic.On, false);
429
- const activeService = this.fanOutlets.get(this.lastActiveFanSpeedMode);
300
+ const activeService = this.fanOutlets.get(this.lastActiveFanSpeed);
430
301
  if (activeService) {
431
302
  activeService.updateCharacteristic(this.Characteristic.On, this.isOn);
432
303
  }
@@ -434,38 +305,23 @@ export class AirConditioner {
434
305
  return;
435
306
  }
436
307
  this.isOn = true;
437
- this.lastActiveFanSpeedMode = fanspeedMode;
308
+ this.lastActiveFanSpeed = speed;
438
309
  for (const [fanSpeed, service] of this.fanOutlets.entries()) {
439
- if (fanSpeed !== fanspeedMode) {
310
+ if (fanSpeed !== speed) {
440
311
  service.updateCharacteristic(this.Characteristic.On, false);
441
312
  }
442
313
  }
443
314
  this.acThermostat.updateCharacteristic(this.Characteristic.Active, 1);
444
- const stateVal = this.lastActiveMode === this.MODE_FANONLY ? 1 : 3;
315
+ const stateVal = this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' ? 1 : 3;
445
316
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, stateVal);
446
317
  for (const [modeKey, service] of this.modeOutlets.entries()) {
447
318
  service.updateCharacteristic(this.Characteristic.On, this.lastActiveMode === modeKey);
448
319
  }
449
- const cmdBody = {
450
- command: {
451
- fanspeed: this.lastActiveFanSpeedMode,
452
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
453
- },
454
- kind: 'service#command',
455
- deviceId: this.deviceId,
456
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
457
- serviceType: 'cloud.smarthq.service.thermostat.v1',
458
- domainType: 'cloud.smarthq.domain.thermostat',
459
- };
460
- this.client.debug(chalk.yellow('## Setting Fan Speed from mode:' + this.lastActiveMode));
461
- this.client.debug(chalk.yellow(JSON.stringify(cmdBody, null, 2)));
462
- this.sendCommand(cmdBody);
320
+ this.sendCommand();
463
321
  }
464
322
  else {
465
323
  // Toggling active fan speed OFF powers down system
466
- // note: Fan Speed OFF is not a supported state for the AC unit, so we treat it as a power down command
467
- // note: don't think the else block is ever reached
468
- if (this.lastActiveFanSpeedMode === fanspeedMode) {
324
+ if (this.lastActiveFanSpeed === speed) {
469
325
  this.isOn = false;
470
326
  for (const service of this.modeOutlets.values()) {
471
327
  service.updateCharacteristic(this.Characteristic.On, false);
@@ -475,110 +331,76 @@ export class AirConditioner {
475
331
  }
476
332
  this.acThermostat.updateCharacteristic(this.Characteristic.Active, 0);
477
333
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, 0);
478
- const cmdBody = {
479
- command: {
480
- on: this.isOn,
481
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
482
- },
483
- kind: 'service#command',
484
- deviceId: this.deviceId,
485
- serviceDeviceType: 'cloud.smarthq.device.airconditioner',
486
- serviceType: 'cloud.smarthq.service.thermostat.v1',
487
- domainType: 'cloud.smarthq.domain.thermostat',
488
- };
489
- this.sendCommand(cmdBody);
334
+ this.sendCommand();
490
335
  }
491
336
  }
492
337
  });
493
338
  }
494
339
  }
495
- // D. Add Debug State switch to parent accessory
496
- this.addDebugState('cloud.smarthq.service.thermostat.v1');
497
340
  }
498
341
  // ---------------------------
499
342
  // API COMMAND SENDER
500
343
  // ---------------------------
501
- async sendCommand(cmdBody) {
502
- try {
503
- const response = await this.client.sendCommand(cmdBody); // This command sets the mode and options
504
- if (response == null) {
505
- this.client.debug("No response from setActive command");
506
- return false;
344
+ sendCommand() {
345
+ if (this.debounceTimeout) {
346
+ clearTimeout(this.debounceTimeout);
347
+ }
348
+ this.debounceTimeout = setTimeout(() => {
349
+ this.debounceTimeout = null;
350
+ this.executeSendCommand();
351
+ }, 150);
352
+ }
353
+ async executeSendCommand() {
354
+ const service = this.findService('cloud.smarthq.service.thermostat.v1', 'cloud.smarthq.domain.thermostat');
355
+ if (!service)
356
+ return;
357
+ this.commandQueue = this.commandQueue.then(async () => {
358
+ const command = {
359
+ commandType: 'cloud.smarthq.command.thermostat.v1.set',
360
+ };
361
+ // Only send the 'on' parameter if it is transitioning (prevents GE firmware from resetting to ECO)
362
+ if (!this.isOn) {
363
+ command.on = false;
507
364
  }
508
- else {
509
- this.client.debug("=======================Response from set command : " + response.outcome);
510
- return response.success;
365
+ else if (!this.physicalOnState) {
366
+ command.on = true;
511
367
  }
512
- }
513
- catch (error) {
514
- console.warn("Error sending setActive command: " + error);
515
- }
368
+ if (this.isOn) {
369
+ command.mode = this.lastActiveMode;
370
+ // Handle behavior constraint: Fan Only mode does not support Auto Fan Speed
371
+ if (this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' &&
372
+ this.lastActiveFanSpeed === 'cloud.smarthq.type.fanspeed.auto') {
373
+ command.fanSpeed = 'cloud.smarthq.type.fanspeed.low';
374
+ }
375
+ else {
376
+ command.fanSpeed = this.lastActiveFanSpeed;
377
+ }
378
+ // Omit coolFahrenheit in Fan Only mode (thermostat has no cooling setpoint)
379
+ if (this.lastActiveMode !== 'cloud.smarthq.type.thermostatmode.fanonly') {
380
+ // Clip celsius to hardware bounds to prevent API errors
381
+ const clippedCelsius = Math.max(this.coolCelsiusMin, Math.min(this.coolCelsiusMax, this.lastActiveCelsius));
382
+ command.coolFahrenheit = Math.round(clippedCelsius * 1.8 + 32);
383
+ }
384
+ }
385
+ this.client.debug('## 1.2.5-test.0 -> command = ' + JSON.stringify(command, null, 2));
386
+ try {
387
+ await this.client.sendCommand({
388
+ command,
389
+ kind: 'service#command',
390
+ deviceId: this.deviceId,
391
+ serviceDeviceType: 'cloud.smarthq.device.airconditioner',
392
+ serviceType: 'cloud.smarthq.service.thermostat.v1',
393
+ domainType: 'cloud.smarthq.domain.thermostat',
394
+ });
395
+ }
396
+ catch (error) {
397
+ this.platform.log.error(`Error sending command to AC:`, error);
398
+ }
399
+ }).catch((err) => {
400
+ this.platform.log.error(`Error in AC command queue:`, err);
401
+ });
402
+ return this.commandQueue;
516
403
  }
517
- /*
518
- private async executeSendCommand(command: SendCommandRequest) {
519
- const service = this.findService(
520
- 'cloud.smarthq.service.thermostat.v1',
521
- 'cloud.smarthq.domain.thermostat',
522
- );
523
-
524
- if (!service) return;
525
-
526
- //this.commandQueue = this.commandQueue.then(async () => {
527
-
528
- const command: Record<string, unknown> = {
529
- commandType: 'cloud.smarthq.command.thermostat.v1.set',
530
- };
531
-
532
-
533
- // Only send the 'on' parameter if it is transitioning (prevents GE firmware from resetting to ECO)
534
- if (!this.isOn) {
535
- command.on = false;
536
- } else if (!this.physicalOnState) {
537
- command.on = true;
538
- }
539
-
540
- if (this.isOn) {
541
- command.mode = this.lastActiveMode;
542
-
543
- // Handle behavior constraint: Fan Only mode does not support Auto Fan Speed
544
- if (
545
- this.lastActiveMode === this.MODE_FANONLY &&
546
- this.lastActiveFanSpeedMode === this.FAN_SPEED_AUTO
547
- ) {
548
- command.fanSpeed = this.FAN_SPEED_LOW;
549
- } else {
550
- command.fanSpeed = this.lastActiveFanSpeedMode;
551
- }
552
-
553
- // Omit coolFahrenheit in Fan Only mode (thermostat has no cooling setpoint)
554
- if (this.lastActiveMode !== this.MODE_FANONLY) {
555
- // Clip celsius to hardware bounds to prevent API errors
556
- const clippedCelsius = Math.max(
557
- this.coolCelsiusMin,
558
- Math.min(this.coolCelsiusMax, this.lastActiveCelsius),
559
- );
560
- command.coolFahrenheit = Math.round(clippedCelsius * 1.8 + 32);
561
- }
562
- }
563
-
564
-
565
- try {
566
- const response = await this.client.sendCommand(command);
567
-
568
- if (response == null) {
569
- this.client.debug("No response from send command");
570
- } else {
571
- this.client.debug(
572
- "#### Response from send command : " + response.outcome,
573
- );
574
- return response.success;
575
- }
576
- } catch (error) {
577
- this.platform.log.error(`Error sending command to AC:`, error);
578
- }
579
-
580
- return true;
581
- }*/
582
404
  // ---------------------------
583
405
  // WEBSOCKET UPDATES HANDLING
584
406
  // ---------------------------
@@ -600,19 +422,19 @@ export class AirConditioner {
600
422
  this.lastActiveMode = state.mode;
601
423
  }
602
424
  if (state.fanSpeed !== undefined) {
603
- this.lastActiveFanSpeedMode = state.fanSpeed;
425
+ this.lastActiveFanSpeed = state.fanSpeed;
604
426
  }
605
427
  // Update HeaterCooler state dynamically based on power and mode
606
428
  const stateVal = !this.isOn
607
429
  ? 0
608
- : (this.lastActiveMode === this.MODE_FANONLY ? 1 : 3);
430
+ : (this.lastActiveMode === 'cloud.smarthq.type.thermostatmode.fanonly' ? 1 : 3);
609
431
  this.acThermostat.updateCharacteristic(this.Characteristic.CurrentHeaterCoolerState, stateVal);
610
432
  // Update dynamic outlets
611
433
  for (const [mode, service] of this.modeOutlets.entries()) {
612
434
  service.updateCharacteristic(this.Characteristic.On, this.isOn && this.lastActiveMode === mode);
613
435
  }
614
436
  for (const [fanSpeed, service] of this.fanOutlets.entries()) {
615
- service.updateCharacteristic(this.Characteristic.On, this.isOn && this.lastActiveFanSpeedMode === fanSpeed);
437
+ service.updateCharacteristic(this.Characteristic.On, this.isOn && this.lastActiveFanSpeed === fanSpeed);
616
438
  }
617
439
  }
618
440
  else if (message.domainType === 'cloud.smarthq.domain.indoor.ambient') {
@@ -648,55 +470,5 @@ export class AirConditioner {
648
470
  this.platform.log.error(`Failed to connect to SmartHQ WebSocket for AC ${this.deviceId}:`, error);
649
471
  }
650
472
  }
651
- // ---------------------------
652
- // HELPERS FOR DEBUGGING
653
- // Adds a 'Debug State' switch to the parent accessory that logs the current state of the specified service type when toggled on
654
- // ---------------------------
655
- addDebugState(serviceType) {
656
- const debugState = this.setupService('Switch', 'Debug State', `${this.deviceId}-debug-state`);
657
- debugState
658
- .getCharacteristic(this.Characteristic.On)
659
- .onGet(() => {
660
- return debugState.getCharacteristic(this.Characteristic.On).value;
661
- })
662
- .onSet(async (value) => {
663
- if (value) {
664
- const response = await this.client.getDevice(this.deviceId);
665
- const deviceServices = response.services ?? [];
666
- for (const service of deviceServices) {
667
- if (service.serviceType === serviceType) {
668
- this.client.debug('Debug State - Device Info: ' + JSON.stringify(service, null, 2));
669
- }
670
- }
671
- setTimeout(() => {
672
- debugState.updateCharacteristic(this.Characteristic.On, false);
673
- }, 1000);
674
- }
675
- });
676
- }
677
- setupService(serviceType, displayName, serviceIdSuffix) {
678
- let service;
679
- switch (serviceType) {
680
- case 'Outlet':
681
- service =
682
- this.accessory.getService(displayName) ||
683
- this.accessory.addService(this.Service.Outlet, displayName, serviceIdSuffix);
684
- break;
685
- case 'Switch':
686
- service =
687
- this.accessory.getService(displayName) ||
688
- this.accessory.addService(this.Service.Switch, displayName, serviceIdSuffix);
689
- break;
690
- default:
691
- this.client.debug('Unknown service type: ' + serviceType + '');
692
- service =
693
- this.accessory.getService(displayName) ||
694
- this.accessory.addService(this.Service.Fan, displayName, serviceIdSuffix);
695
- }
696
- service.setCharacteristic(this.Characteristic.Name, displayName);
697
- service.addOptionalCharacteristic(this.Characteristic.ConfiguredName);
698
- service.setCharacteristic(this.Characteristic.ConfiguredName, displayName);
699
- return service;
700
- }
701
473
  }
702
474
  //# sourceMappingURL=airConditioner.js.map