homebridge-smarthq-client 1.3.0 → 1.3.1
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/.github/workflows/release.yml +5 -3
- package/CHANGELOG.md +8 -0
- package/dist/dishwasher/dishwasher.d.ts +19 -2
- package/dist/dishwasher/dishwasher.js +121 -72
- package/dist/dishwasher/dishwasher.js.map +1 -1
- package/jest.config.cjs +1 -1
- package/jest.config.mjs +12 -0
- package/package.json +3 -3
- package/src/dishwasher/dishwasher.ts +235 -78
- package/tsconfig.json +1 -0
|
@@ -21,9 +21,9 @@ jobs:
|
|
|
21
21
|
persist-credentials: false
|
|
22
22
|
|
|
23
23
|
- name: Setup Node.js
|
|
24
|
-
uses: actions/setup-node@
|
|
24
|
+
uses: actions/setup-node@v7
|
|
25
25
|
with:
|
|
26
|
-
node-version: 24
|
|
26
|
+
node-version: '24.10'
|
|
27
27
|
cache: 'npm'
|
|
28
28
|
|
|
29
29
|
- name: Install Dependencies
|
|
@@ -33,7 +33,9 @@ jobs:
|
|
|
33
33
|
run: npm run build --if-present
|
|
34
34
|
|
|
35
35
|
- name: Run Tests
|
|
36
|
-
run: npm test --if-present
|
|
36
|
+
run: npm test --if-present
|
|
37
|
+
env:
|
|
38
|
+
NODE_OPTIONS: --experimental-vm-modules
|
|
37
39
|
|
|
38
40
|
- name: Semantic Release
|
|
39
41
|
env:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [1.3.1](https://github.com/ceb400/homebridge-smarthq-client/compare/v1.3.0...v1.3.1) (2026-09-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* :bug: dishwasher options initialized wrong ([ee59785](https://github.com/ceb400/homebridge-smarthq-client/commit/ee59785bbdc33a7373a8d0dfe0b766f0101ac1e2))
|
|
7
|
+
* :bug: Fix Dishwasher Cleaning mode error. Replace Cycle Pct Done with new Time remaining ([a1738bb](https://github.com/ceb400/homebridge-smarthq-client/commit/a1738bbe3e36217c0476d89ffcbe1f5682909776))
|
|
8
|
+
|
|
1
9
|
# Changelog
|
|
2
10
|
|
|
3
11
|
All notable changes to this project will be documented in this file.
|
|
@@ -2,9 +2,13 @@ import { CharacteristicValue, PlatformAccessory, Service, Characteristic } from
|
|
|
2
2
|
import { DeviceService } from "ge-smarthq";
|
|
3
3
|
import { SmartHqPlatform } from "../platform.js";
|
|
4
4
|
/**
|
|
5
|
+
|
|
5
6
|
* Platform Accessory
|
|
7
|
+
|
|
6
8
|
* An instance of this class is created for each accessory your platform registers
|
|
9
|
+
|
|
7
10
|
* Each accessory may expose multiple services of different service types
|
|
11
|
+
|
|
8
12
|
*/
|
|
9
13
|
export declare class Dishwasher {
|
|
10
14
|
private readonly platform;
|
|
@@ -50,36 +54,48 @@ export declare class Dishwasher {
|
|
|
50
54
|
private readonly SANI_AND_BOOST_TEMP;
|
|
51
55
|
constructor(platform: SmartHqPlatform, accessory: PlatformAccessory, deviceServices: DeviceService[], deviceId: string, groupAccessory: PlatformAccessory[]);
|
|
52
56
|
/**
|
|
57
|
+
|
|
53
58
|
* Handle requests to get the current value of the "Active" characteristic
|
|
59
|
+
|
|
54
60
|
*/
|
|
55
61
|
handleSetDurationGet(): Promise<CharacteristicValue>;
|
|
56
62
|
/**
|
|
63
|
+
|
|
57
64
|
* Handle requests to get the current value of the "Active" characteristic
|
|
65
|
+
|
|
58
66
|
*/
|
|
59
67
|
handleActiveGet(): Promise<CharacteristicValue>;
|
|
60
68
|
/**
|
|
69
|
+
|
|
61
70
|
* Handle requests to set the "Active" characteristic
|
|
71
|
+
|
|
62
72
|
*/
|
|
63
73
|
handleActiveSet(value: CharacteristicValue): Promise<void>;
|
|
64
74
|
/**
|
|
75
|
+
|
|
65
76
|
* Handle requests to get the current value of the "In Use" characteristic
|
|
77
|
+
|
|
66
78
|
*/
|
|
67
79
|
handleInUseGet(): Promise<CharacteristicValue>;
|
|
68
80
|
/**
|
|
81
|
+
|
|
69
82
|
* Handle requests to get the current value of the "Name" characteristic
|
|
83
|
+
|
|
70
84
|
*/
|
|
71
85
|
handleNameGet(): Promise<string | false>;
|
|
72
86
|
/**
|
|
87
|
+
|
|
73
88
|
* Handle requests to get the current value of the "mode" value
|
|
89
|
+
|
|
74
90
|
*/
|
|
75
91
|
handleModeGet(v1mode: string): Promise<CharacteristicValue>;
|
|
76
92
|
/**
|
|
93
|
+
|
|
77
94
|
* Handle requests to get the current value of the "Valve Type" characteristic
|
|
95
|
+
|
|
78
96
|
*/
|
|
79
97
|
handleValveTypeGet(): Promise<number>;
|
|
80
98
|
handleRemainingTimeGet(): Promise<CharacteristicValue>;
|
|
81
|
-
getCyclePct(): Promise<CharacteristicValue>;
|
|
82
|
-
setCyclePct(value: CharacteristicValue): Promise<CharacteristicValue>;
|
|
83
99
|
setMode(): Promise<boolean>;
|
|
84
100
|
private formatError;
|
|
85
101
|
startCycle(): Promise<boolean>;
|
|
@@ -96,6 +112,7 @@ export declare class Dishwasher {
|
|
|
96
112
|
getLastElementAndCapitalize(str: string, delimiter: string): [string, string];
|
|
97
113
|
setupWebSocket(): Promise<void>;
|
|
98
114
|
logCurrentOptions(): void;
|
|
115
|
+
updateDurationTimerDisplay(remainingSeconds: number): void;
|
|
99
116
|
testCases(): Promise<false | undefined>;
|
|
100
117
|
testSetMode({ mode, temp, dry, zone, bottle, steam, silverware }: {
|
|
101
118
|
mode?: string;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { SmartHQClient } from "ge-smarthq";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
/**
|
|
4
|
+
|
|
4
5
|
* Platform Accessory
|
|
6
|
+
|
|
5
7
|
* An instance of this class is created for each accessory your platform registers
|
|
8
|
+
|
|
6
9
|
* Each accessory may expose multiple services of different service types
|
|
10
|
+
|
|
7
11
|
*/
|
|
8
12
|
export class Dishwasher {
|
|
9
13
|
platform;
|
|
@@ -37,7 +41,7 @@ export class Dishwasher {
|
|
|
37
41
|
ONE_HOUR_MODE = "cloud.smarthq.domain.dishwasher.timed.hours.1";
|
|
38
42
|
PLATPLUS_MODE = "cloud.smarthq.domain.dishwasher.brand.cascade.platinumplus";
|
|
39
43
|
RINSE_MODE = "cloud.smarthq.domain.dishwasher.rinse";
|
|
40
|
-
CLEAN_MODE = "cloud.smarthq.domain.dishwasher.
|
|
44
|
+
CLEAN_MODE = "cloud.smarthq.domain.dishwasher.dishwasher.cleaning";
|
|
41
45
|
LIGHT_MODE = "cloud.smarthq.domain.dishwasher.light";
|
|
42
46
|
//======== wash zone constants ========
|
|
43
47
|
BOTH_ZONE = "cloud.smarthq.type.dishwasher.washzone.both";
|
|
@@ -81,26 +85,25 @@ export class Dishwasher {
|
|
|
81
85
|
}
|
|
82
86
|
this.setupWebSocket();
|
|
83
87
|
/*
|
|
88
|
+
|
|
84
89
|
* Listen for WebSocket messages for this device and update HomeKit characteristics accordingly
|
|
90
|
+
|
|
85
91
|
*/
|
|
86
92
|
this.client.on("service_update", (message) => {
|
|
87
|
-
//this.client.debug(chalk.red('Wash Modes - Service Update:'+ JSON.stringify(message, null, 2)));
|
|
88
93
|
if (message.domainType === "cloud.smarthq.domain.energy"
|
|
89
94
|
&& message.deviceType === "cloud.smarthq.device.dishwasher") {
|
|
90
95
|
this.energyMeterValuePerHour += message.state?.meterValueDelta || 0; // sum for the hour until reset
|
|
96
|
+
this.client.debug(chalk.white('Energy Meter Value: ' + this.energyMeterValuePerHour));
|
|
91
97
|
}
|
|
98
|
+
// Update the time remaining from the WebSocket message if it is a cycle timer update
|
|
99
|
+
// Update the ConfiguredName of the durationTimer service to show the time remaining in the cycle or the current time if no cycle is active
|
|
92
100
|
if (message.serviceType === "cloud.smarthq.service.cycletimer" &&
|
|
93
101
|
message.domainType === "cloud.smarthq.domain.cycle") {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this.totalSeconds = 0;
|
|
97
|
-
}
|
|
102
|
+
this.timeRemainingFromWebSocket =
|
|
103
|
+
message.state?.secondsRemaining || 0;
|
|
98
104
|
if (this.totalSeconds === 0) {
|
|
99
105
|
this.totalSeconds = message.state?.secondsRemaining || 0;
|
|
100
106
|
}
|
|
101
|
-
this.timeRemainingFromWebSocket =
|
|
102
|
-
message.state?.secondsRemaining || 0;
|
|
103
|
-
this.getCyclePct();
|
|
104
107
|
}
|
|
105
108
|
if (message.state?.mode != null) {
|
|
106
109
|
switch (message.state.mode) {
|
|
@@ -138,6 +141,10 @@ export class Dishwasher {
|
|
|
138
141
|
this.client.debug(chalk.red("Watts/hour value: " + this.energyMeterValuePerHour));
|
|
139
142
|
this.energyMeterValuePerHour = 0;
|
|
140
143
|
}, 60 * 60 * 1000);
|
|
144
|
+
// Interval to update configured name of durationTimer service every minute to show time remaining in cycle or current time if no cycle is active
|
|
145
|
+
setInterval(() => {
|
|
146
|
+
this.updateDurationTimerDisplay(this.timeRemainingFromWebSocket);
|
|
147
|
+
}, 60 * 1000);
|
|
141
148
|
const washTemps = this.getAvailableItemsByType("washTempAvailable");
|
|
142
149
|
const washZones = this.getAvailableItemsByType("washZoneAvailable");
|
|
143
150
|
const heatedDrys = this.getAvailableItemsByType("heatedDryAvailable");
|
|
@@ -199,21 +206,23 @@ export class Dishwasher {
|
|
|
199
206
|
dishwasher
|
|
200
207
|
.getCharacteristic(this.Characteristic.Name)
|
|
201
208
|
.onGet(this.handleNameGet.bind(this));
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
.
|
|
213
|
-
|
|
214
|
-
|
|
209
|
+
// Test dynamically changing configured name to use as a text field
|
|
210
|
+
const customName = "Time Display";
|
|
211
|
+
const durationTimer = this.setupService("Outlet", customName, `${this.deviceId}-optionstimer`);
|
|
212
|
+
durationTimer
|
|
213
|
+
.getCharacteristic(this.Characteristic.On)
|
|
214
|
+
.onGet(() => {
|
|
215
|
+
const currentState = durationTimer.getCharacteristic(this.Characteristic.On)
|
|
216
|
+
.value;
|
|
217
|
+
return currentState; // Return true or false
|
|
218
|
+
})
|
|
219
|
+
.onSet((value) => {
|
|
220
|
+
this.client.debug(chalk.yellow(`Time Display On/Off set to: ${value}`));
|
|
221
|
+
});
|
|
215
222
|
/**
|
|
223
|
+
|
|
216
224
|
* create a new steam Outlet service Dummy (used as 'available' option) ------
|
|
225
|
+
|
|
217
226
|
*/
|
|
218
227
|
displayName = "Steam option";
|
|
219
228
|
const optionSteam = this.setupService("Outlet", displayName, `${this.deviceId}-optionsteam`);
|
|
@@ -229,7 +238,9 @@ export class Dishwasher {
|
|
|
229
238
|
this.testSetMode({ steam: value });
|
|
230
239
|
});
|
|
231
240
|
/**
|
|
241
|
+
|
|
232
242
|
* create a new bottlewash Outlet service Dummy (used as 'available' option) for extending presets ------
|
|
243
|
+
|
|
233
244
|
*/
|
|
234
245
|
displayName = "Bottlewash option";
|
|
235
246
|
const optionBottlewash = this.setupService("Outlet", displayName, `${this.deviceId}-optionbottlewash`);
|
|
@@ -245,7 +256,9 @@ export class Dishwasher {
|
|
|
245
256
|
this.testSetMode({ bottle: value });
|
|
246
257
|
});
|
|
247
258
|
/**
|
|
259
|
+
|
|
248
260
|
* create a new silverware Outlet service Dummy (used as 'available' option) for extending presets ------
|
|
261
|
+
|
|
249
262
|
*/
|
|
250
263
|
displayName = "Silverware option";
|
|
251
264
|
const optionSilverware = this.setupService("Outlet", displayName, `${this.deviceId}-option-silverware`);
|
|
@@ -261,7 +274,9 @@ export class Dishwasher {
|
|
|
261
274
|
this.testSetMode({ silverware: this.currentSilverwareWash });
|
|
262
275
|
});
|
|
263
276
|
/**
|
|
277
|
+
|
|
264
278
|
* Grouped services for Wash Temp, Dry Level, Wash Zone, and Preset Modes - only one can be on at a time within each group
|
|
279
|
+
|
|
265
280
|
*/
|
|
266
281
|
this.client.debug(chalk.green("Wash Temperature options"));
|
|
267
282
|
const temps = washTemps.map(([item]) => this.setupGroupService("Outlet", item, "modegroup-" + item.replace(/\s+/g, "-").toLowerCase(), this.groupAccessory[0]));
|
|
@@ -495,6 +510,7 @@ export class Dishwasher {
|
|
|
495
510
|
// NOTE: only for developing a method for testing command combinations.
|
|
496
511
|
// this.testCases();
|
|
497
512
|
/*
|
|
513
|
+
|
|
498
514
|
for (const service of this.deviceServices) {
|
|
499
515
|
if (
|
|
500
516
|
service.serviceDeviceType === "cloud.smarthq.device.dishwasher" &&
|
|
@@ -516,18 +532,24 @@ export class Dishwasher {
|
|
|
516
532
|
}
|
|
517
533
|
|
|
518
534
|
//const originalPresetMode = response?.state.
|
|
535
|
+
|
|
519
536
|
}
|
|
520
537
|
}
|
|
538
|
+
|
|
521
539
|
*/
|
|
522
540
|
}
|
|
523
541
|
/**
|
|
542
|
+
|
|
524
543
|
* Handle requests to get the current value of the "Active" characteristic
|
|
544
|
+
|
|
525
545
|
*/
|
|
526
546
|
async handleSetDurationGet() {
|
|
527
547
|
return this.totalSeconds;
|
|
528
548
|
}
|
|
529
549
|
/**
|
|
550
|
+
|
|
530
551
|
* Handle requests to get the current value of the "Active" characteristic
|
|
552
|
+
|
|
531
553
|
*/
|
|
532
554
|
async handleActiveGet() {
|
|
533
555
|
let isActive = false;
|
|
@@ -541,25 +563,11 @@ export class Dishwasher {
|
|
|
541
563
|
this.client.debug("No response from dishwasher run status request");
|
|
542
564
|
return false;
|
|
543
565
|
}
|
|
544
|
-
if (response.state.runStatus === "cloud.smarthq.type.runstatus.
|
|
566
|
+
if (response.state.runStatus === "cloud.smarthq.type.runstatus.endofcycle"
|
|
567
|
+
|| response.state.runStatus === "cloud.smarthq.type.runstatus.off") {
|
|
545
568
|
// change back to 0 seconds remaining when cycle is not active to prevent stale remaining time value in HomeKit
|
|
546
569
|
this.totalSeconds = 0; // reset total seconds when cycle is complete
|
|
547
|
-
this.
|
|
548
|
-
.getService("Dishwasher")
|
|
549
|
-
?.getCharacteristic(this.Characteristic.Active)
|
|
550
|
-
.updateValue(false);
|
|
551
|
-
this.accessory
|
|
552
|
-
.getService("Dishwasher")
|
|
553
|
-
?.getCharacteristic(this.Characteristic.SetDuration)
|
|
554
|
-
.updateValue(0);
|
|
555
|
-
this.accessory
|
|
556
|
-
.getService("Dishwasher")
|
|
557
|
-
?.getCharacteristic(this.Characteristic.RemainingDuration)
|
|
558
|
-
.updateValue(0);
|
|
559
|
-
this.accessory
|
|
560
|
-
.getService("Dishwasher")
|
|
561
|
-
?.getCharacteristic(this.Characteristic.InUse)
|
|
562
|
-
.updateValue(false);
|
|
570
|
+
this.updateDurationTimerDisplay(this.totalSeconds);
|
|
563
571
|
}
|
|
564
572
|
else {
|
|
565
573
|
isActive = true;
|
|
@@ -570,7 +578,7 @@ export class Dishwasher {
|
|
|
570
578
|
this.accessory
|
|
571
579
|
.getService("Dishwasher")
|
|
572
580
|
?.getCharacteristic(this.Characteristic.InUse)
|
|
573
|
-
.updateValue(
|
|
581
|
+
.updateValue(this.Characteristic.InUse.IN_USE);
|
|
574
582
|
}
|
|
575
583
|
break;
|
|
576
584
|
}
|
|
@@ -583,7 +591,9 @@ export class Dishwasher {
|
|
|
583
591
|
return isActive;
|
|
584
592
|
}
|
|
585
593
|
/**
|
|
594
|
+
|
|
586
595
|
* Handle requests to set the "Active" characteristic
|
|
596
|
+
|
|
587
597
|
*/
|
|
588
598
|
async handleActiveSet(value) {
|
|
589
599
|
this.client.debug(`Starting dishwasher active state: ${value}`);
|
|
@@ -611,7 +621,9 @@ export class Dishwasher {
|
|
|
611
621
|
}
|
|
612
622
|
}
|
|
613
623
|
/**
|
|
624
|
+
|
|
614
625
|
* Handle requests to get the current value of the "In Use" characteristic
|
|
626
|
+
|
|
615
627
|
*/
|
|
616
628
|
async handleInUseGet() {
|
|
617
629
|
//this.client.debug('Triggered GET InUse');
|
|
@@ -620,7 +632,9 @@ export class Dishwasher {
|
|
|
620
632
|
return this.handleActiveGet();
|
|
621
633
|
}
|
|
622
634
|
/**
|
|
635
|
+
|
|
623
636
|
* Handle requests to get the current value of the "Name" characteristic
|
|
637
|
+
|
|
624
638
|
*/
|
|
625
639
|
async handleNameGet() {
|
|
626
640
|
//this.client.debug('Triggered GET Name');
|
|
@@ -646,7 +660,9 @@ export class Dishwasher {
|
|
|
646
660
|
return this.accessory.displayName;
|
|
647
661
|
}
|
|
648
662
|
/**
|
|
663
|
+
|
|
649
664
|
* Handle requests to get the current value of the "mode" value
|
|
665
|
+
|
|
650
666
|
*/
|
|
651
667
|
async handleModeGet(v1mode) {
|
|
652
668
|
let isOn = false;
|
|
@@ -657,10 +673,12 @@ export class Dishwasher {
|
|
|
657
673
|
try {
|
|
658
674
|
const response = await this.client.getServiceDetails(this.deviceId, service.serviceId);
|
|
659
675
|
/*
|
|
676
|
+
|
|
660
677
|
this.client.debug(
|
|
661
678
|
"================ Response from getServiceDetails for mode get: " +
|
|
662
679
|
JSON.stringify(response, null, 2),
|
|
663
680
|
);
|
|
681
|
+
|
|
664
682
|
*/
|
|
665
683
|
if (response?.state?.mode == null) {
|
|
666
684
|
this.client.debug("No response from dishwasher mode request");
|
|
@@ -678,7 +696,9 @@ export class Dishwasher {
|
|
|
678
696
|
return isOn;
|
|
679
697
|
}
|
|
680
698
|
/**
|
|
699
|
+
|
|
681
700
|
* Handle requests to get the current value of the "Valve Type" characteristic
|
|
701
|
+
|
|
682
702
|
*/
|
|
683
703
|
async handleValveTypeGet() {
|
|
684
704
|
//this.client.debug('Triggered GET ValveType');
|
|
@@ -698,34 +718,6 @@ export class Dishwasher {
|
|
|
698
718
|
}
|
|
699
719
|
return this.totalSeconds;
|
|
700
720
|
}
|
|
701
|
-
async getCyclePct() {
|
|
702
|
-
// remaining time appears able to change after a cycle has started???
|
|
703
|
-
if (this.timeRemainingFromWebSocket > this.totalSeconds) {
|
|
704
|
-
this.totalSeconds = this.timeRemainingFromWebSocket;
|
|
705
|
-
}
|
|
706
|
-
const pctDone = 100 - Math.round((this.timeRemainingFromWebSocket / this.totalSeconds) * 100) || 0;
|
|
707
|
-
this.setCyclePct(pctDone);
|
|
708
|
-
if (this.timeRemainingFromWebSocket === 0) {
|
|
709
|
-
this.accessory
|
|
710
|
-
.getService("Cycle Pct Done")
|
|
711
|
-
?.getCharacteristic(this.Characteristic.On)
|
|
712
|
-
.updateValue(false);
|
|
713
|
-
}
|
|
714
|
-
else {
|
|
715
|
-
this.accessory
|
|
716
|
-
.getService("Cycle Pct Done")
|
|
717
|
-
?.getCharacteristic(this.Characteristic.On)
|
|
718
|
-
.updateValue(true);
|
|
719
|
-
this.accessory.getService("Cycle Pct Done")?.updateCharacteristic(this.Characteristic.Brightness, pctDone);
|
|
720
|
-
}
|
|
721
|
-
return pctDone;
|
|
722
|
-
}
|
|
723
|
-
async setCyclePct(value) {
|
|
724
|
-
this.accessory
|
|
725
|
-
.getService("Cycle Pct Done")
|
|
726
|
-
?.updateCharacteristic(this.Characteristic.Brightness, value);
|
|
727
|
-
return value;
|
|
728
|
-
}
|
|
729
721
|
async setMode() {
|
|
730
722
|
const baseCommand = {
|
|
731
723
|
deviceId: this.deviceId,
|
|
@@ -776,6 +768,16 @@ export class Dishwasher {
|
|
|
776
768
|
},
|
|
777
769
|
};
|
|
778
770
|
break;
|
|
771
|
+
case this.CLEAN_MODE:
|
|
772
|
+
cmdBody = {
|
|
773
|
+
...baseCommand,
|
|
774
|
+
domainType: this.currentPreset,
|
|
775
|
+
command: {
|
|
776
|
+
washTemp: this.currentWashTemp,
|
|
777
|
+
commandType: "cloud.smarthq.command.dishwasher.mode.v1.set",
|
|
778
|
+
},
|
|
779
|
+
};
|
|
780
|
+
break;
|
|
779
781
|
case this.ONE_HOUR_MODE:
|
|
780
782
|
cmdBody = {
|
|
781
783
|
...baseCommand,
|
|
@@ -862,7 +864,7 @@ export class Dishwasher {
|
|
|
862
864
|
this.accessory
|
|
863
865
|
.getService("Dishwasher")
|
|
864
866
|
?.getCharacteristic(this.Characteristic.InUse)
|
|
865
|
-
.updateValue(
|
|
867
|
+
.updateValue(this.Characteristic.InUse.IN_USE);
|
|
866
868
|
this.accessory
|
|
867
869
|
.getService("Dishwasher")
|
|
868
870
|
?.getCharacteristic(this.Characteristic.SetDuration)
|
|
@@ -870,7 +872,7 @@ export class Dishwasher {
|
|
|
870
872
|
this.accessory
|
|
871
873
|
.getService("Dishwasher")
|
|
872
874
|
?.getCharacteristic(this.Characteristic.RemainingDuration)
|
|
873
|
-
.updateValue(this.
|
|
875
|
+
.updateValue(this.timeRemainingFromWebSocket);
|
|
874
876
|
return response.success;
|
|
875
877
|
}
|
|
876
878
|
}
|
|
@@ -900,7 +902,7 @@ export class Dishwasher {
|
|
|
900
902
|
this.accessory
|
|
901
903
|
.getService("Dishwasher")
|
|
902
904
|
?.getCharacteristic(this.Characteristic.InUse)
|
|
903
|
-
.updateValue(
|
|
905
|
+
.updateValue(this.Characteristic.InUse.NOT_IN_USE);
|
|
904
906
|
this.totalSeconds = 0; // reset total seconds when cycle is stopped
|
|
905
907
|
this.accessory
|
|
906
908
|
.getService("Dishwasher")
|
|
@@ -909,7 +911,7 @@ export class Dishwasher {
|
|
|
909
911
|
this.accessory
|
|
910
912
|
.getService("Dishwasher")
|
|
911
913
|
?.getCharacteristic(this.Characteristic.RemainingDuration)
|
|
912
|
-
.updateValue(this.
|
|
914
|
+
.updateValue(this.timeRemainingFromWebSocket);
|
|
913
915
|
return response.success;
|
|
914
916
|
}
|
|
915
917
|
}
|
|
@@ -988,6 +990,7 @@ export class Dishwasher {
|
|
|
988
990
|
accessory.removeService(service);
|
|
989
991
|
});
|
|
990
992
|
}
|
|
993
|
+
// Build a list of available dishwasher option names in a display-friendly format.
|
|
991
994
|
getAvailableItemsByType(availableType) {
|
|
992
995
|
let itemsAvailable = [];
|
|
993
996
|
for (const service of this.deviceServices) {
|
|
@@ -1077,6 +1080,52 @@ export class Dishwasher {
|
|
|
1077
1080
|
this.client.debug(chalk.red("Steam: " + this.currentSteam));
|
|
1078
1081
|
this.client.debug(chalk.red("Silverware Wash: " + this.currentSilverwareWash));
|
|
1079
1082
|
}
|
|
1083
|
+
updateDurationTimerDisplay(remainingSeconds) {
|
|
1084
|
+
const now = new Date();
|
|
1085
|
+
const hours = now.getHours();
|
|
1086
|
+
const minutes = now.getMinutes();
|
|
1087
|
+
if (remainingSeconds > 0) {
|
|
1088
|
+
const remainingHours = Math.floor(remainingSeconds / 3600);
|
|
1089
|
+
const remainingMinutes = Math.floor((remainingSeconds % 3600) / 60);
|
|
1090
|
+
const displayString = `Ends in: ${remainingHours.toString().padStart(2, "0")}:${remainingMinutes.toString().padStart(2, "0")}`;
|
|
1091
|
+
this.accessory
|
|
1092
|
+
.getService("Time Display")
|
|
1093
|
+
?.getCharacteristic(this.Characteristic.ConfiguredName)
|
|
1094
|
+
.updateValue(displayString);
|
|
1095
|
+
this.accessory
|
|
1096
|
+
.getService("Time Display")
|
|
1097
|
+
?.getCharacteristic(this.Characteristic.On)
|
|
1098
|
+
.updateValue(false);
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
const displayString = `Time: ${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
1102
|
+
// when secondsRemaining is 0 then reset totalSeconds to prevent stale values from previous cycles
|
|
1103
|
+
this.totalSeconds = 0;
|
|
1104
|
+
this.accessory
|
|
1105
|
+
.getService("Dishwasher")
|
|
1106
|
+
?.getCharacteristic(this.Characteristic.SetDuration)
|
|
1107
|
+
.updateValue(0);
|
|
1108
|
+
this.accessory
|
|
1109
|
+
.getService("Dishwasher")
|
|
1110
|
+
?.getCharacteristic(this.Characteristic.RemainingDuration)
|
|
1111
|
+
.updateValue(0);
|
|
1112
|
+
this.accessory
|
|
1113
|
+
.getService("Dishwasher")
|
|
1114
|
+
?.getCharacteristic(this.Characteristic.Active)
|
|
1115
|
+
.updateValue(this.Characteristic.Active.INACTIVE);
|
|
1116
|
+
this.accessory
|
|
1117
|
+
.getService("Dishwasher")
|
|
1118
|
+
?.getCharacteristic(this.Characteristic.InUse)
|
|
1119
|
+
.updateValue(this.Characteristic.InUse.NOT_IN_USE);
|
|
1120
|
+
this.accessory
|
|
1121
|
+
.getService("Time Display")
|
|
1122
|
+
?.getCharacteristic(this.Characteristic.ConfiguredName)
|
|
1123
|
+
.updateValue(displayString);
|
|
1124
|
+
this.accessory
|
|
1125
|
+
.getService("Time Display")
|
|
1126
|
+
?.getCharacteristic(this.Characteristic.On)
|
|
1127
|
+
.updateValue(false);
|
|
1128
|
+
}
|
|
1080
1129
|
async testCases() {
|
|
1081
1130
|
//======================================================
|
|
1082
1131
|
// Develop test plan for dishwasher
|