@mp-consulting/homebridge-lg-thinq 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 (241) hide show
  1. package/.claude/settings.local.json +15 -0
  2. package/CHANGELOG.md +98 -0
  3. package/LICENSE +176 -0
  4. package/README.md +114 -0
  5. package/config.schema.json +399 -0
  6. package/dist/__tests__/baseDevice.spec.d.ts +1 -0
  7. package/dist/__tests__/baseDevice.spec.js +96 -0
  8. package/dist/__tests__/baseDevice.spec.js.map +1 -0
  9. package/dist/__tests__/deviceControl.coercion.spec.d.ts +1 -0
  10. package/dist/__tests__/deviceControl.coercion.spec.js +53 -0
  11. package/dist/__tests__/deviceControl.coercion.spec.js.map +1 -0
  12. package/dist/__tests__/helper.spec.d.ts +1 -0
  13. package/dist/__tests__/helper.spec.js +74 -0
  14. package/dist/__tests__/helper.spec.js.map +1 -0
  15. package/dist/baseDevice.d.ts +40 -0
  16. package/dist/baseDevice.js +85 -0
  17. package/dist/baseDevice.js.map +1 -0
  18. package/dist/baseDevice.spec.d.ts +1 -0
  19. package/dist/baseDevice.spec.js +107 -0
  20. package/dist/baseDevice.spec.js.map +1 -0
  21. package/dist/characteristics/TotalConsumption.d.ts +2 -0
  22. package/dist/characteristics/TotalConsumption.js +17 -0
  23. package/dist/characteristics/TotalConsumption.js.map +1 -0
  24. package/dist/characteristics/index.d.ts +2 -0
  25. package/dist/characteristics/index.js +7 -0
  26. package/dist/characteristics/index.js.map +1 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.js +89 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/devices/AeroTower.d.ts +24 -0
  31. package/dist/devices/AeroTower.js +113 -0
  32. package/dist/devices/AeroTower.js.map +1 -0
  33. package/dist/devices/AirConditioner.d.ts +425 -0
  34. package/dist/devices/AirConditioner.js +1253 -0
  35. package/dist/devices/AirConditioner.js.map +1 -0
  36. package/dist/devices/AirPurifier.d.ts +50 -0
  37. package/dist/devices/AirPurifier.js +281 -0
  38. package/dist/devices/AirPurifier.js.map +1 -0
  39. package/dist/devices/Dehumidifier.d.ts +28 -0
  40. package/dist/devices/Dehumidifier.js +175 -0
  41. package/dist/devices/Dehumidifier.js.map +1 -0
  42. package/dist/devices/Dishwasher.d.ts +64 -0
  43. package/dist/devices/Dishwasher.js +740 -0
  44. package/dist/devices/Dishwasher.js.map +1 -0
  45. package/dist/devices/Microwave.d.ts +128 -0
  46. package/dist/devices/Microwave.js +1939 -0
  47. package/dist/devices/Microwave.js.map +1 -0
  48. package/dist/devices/Oven.d.ts +148 -0
  49. package/dist/devices/Oven.js +1850 -0
  50. package/dist/devices/Oven.js.map +1 -0
  51. package/dist/devices/RangeHood.d.ts +16 -0
  52. package/dist/devices/RangeHood.js +99 -0
  53. package/dist/devices/RangeHood.js.map +1 -0
  54. package/dist/devices/Refrigerator.d.ts +50 -0
  55. package/dist/devices/Refrigerator.js +325 -0
  56. package/dist/devices/Refrigerator.js.map +1 -0
  57. package/dist/devices/Styler.d.ts +27 -0
  58. package/dist/devices/Styler.js +76 -0
  59. package/dist/devices/Styler.js.map +1 -0
  60. package/dist/devices/WasherDryer.d.ts +39 -0
  61. package/dist/devices/WasherDryer.js +170 -0
  62. package/dist/devices/WasherDryer.js.map +1 -0
  63. package/dist/devices/WasherDryer2.d.ts +9 -0
  64. package/dist/devices/WasherDryer2.js +16 -0
  65. package/dist/devices/WasherDryer2.js.map +1 -0
  66. package/dist/errors/AuthenticationError.d.ts +2 -0
  67. package/dist/errors/AuthenticationError.js +3 -0
  68. package/dist/errors/AuthenticationError.js.map +1 -0
  69. package/dist/errors/ManualProcessNeeded.d.ts +3 -0
  70. package/dist/errors/ManualProcessNeeded.js +4 -0
  71. package/dist/errors/ManualProcessNeeded.js.map +1 -0
  72. package/dist/errors/MonitorError.d.ts +2 -0
  73. package/dist/errors/MonitorError.js +3 -0
  74. package/dist/errors/MonitorError.js.map +1 -0
  75. package/dist/errors/NotConnectedError.d.ts +3 -0
  76. package/dist/errors/NotConnectedError.js +4 -0
  77. package/dist/errors/NotConnectedError.js.map +1 -0
  78. package/dist/errors/TokenError.d.ts +2 -0
  79. package/dist/errors/TokenError.js +3 -0
  80. package/dist/errors/TokenError.js.map +1 -0
  81. package/dist/errors/TokenExpiredError.d.ts +3 -0
  82. package/dist/errors/TokenExpiredError.js +4 -0
  83. package/dist/errors/TokenExpiredError.js.map +1 -0
  84. package/dist/errors/index.d.ts +6 -0
  85. package/dist/errors/index.js +7 -0
  86. package/dist/errors/index.js.map +1 -0
  87. package/dist/helper.d.ts +24 -0
  88. package/dist/helper.js +66 -0
  89. package/dist/helper.js.map +1 -0
  90. package/dist/helper.spec.d.ts +1 -0
  91. package/dist/helper.spec.js +74 -0
  92. package/dist/helper.spec.js.map +1 -0
  93. package/dist/index.d.ts +6 -0
  94. package/dist/index.js +9 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/lib/API.d.ts +141 -0
  97. package/dist/lib/API.js +362 -0
  98. package/dist/lib/API.js.map +1 -0
  99. package/dist/lib/API.spec.d.ts +1 -0
  100. package/dist/lib/API.spec.js +55 -0
  101. package/dist/lib/API.spec.js.map +1 -0
  102. package/dist/lib/Auth.d.ts +99 -0
  103. package/dist/lib/Auth.js +348 -0
  104. package/dist/lib/Auth.js.map +1 -0
  105. package/dist/lib/Auth.spec.d.ts +1 -0
  106. package/dist/lib/Auth.spec.js +111 -0
  107. package/dist/lib/Auth.spec.js.map +1 -0
  108. package/dist/lib/Device.d.ts +88 -0
  109. package/dist/lib/Device.js +95 -0
  110. package/dist/lib/Device.js.map +1 -0
  111. package/dist/lib/Device.spec.d.ts +1 -0
  112. package/dist/lib/Device.spec.js +53 -0
  113. package/dist/lib/Device.spec.js.map +1 -0
  114. package/dist/lib/DeviceModel.d.ts +164 -0
  115. package/dist/lib/DeviceModel.js +321 -0
  116. package/dist/lib/DeviceModel.js.map +1 -0
  117. package/dist/lib/DeviceModel.spec.d.ts +1 -0
  118. package/dist/lib/DeviceModel.spec.js +90 -0
  119. package/dist/lib/DeviceModel.spec.js.map +1 -0
  120. package/dist/lib/Gateway.d.ts +18 -0
  121. package/dist/lib/Gateway.js +25 -0
  122. package/dist/lib/Gateway.js.map +1 -0
  123. package/dist/lib/Gateway.spec.d.ts +1 -0
  124. package/dist/lib/Gateway.spec.js +35 -0
  125. package/dist/lib/Gateway.spec.js.map +1 -0
  126. package/dist/lib/Persist.d.ts +101 -0
  127. package/dist/lib/Persist.js +245 -0
  128. package/dist/lib/Persist.js.map +1 -0
  129. package/dist/lib/Persist.spec.d.ts +1 -0
  130. package/dist/lib/Persist.spec.js +90 -0
  131. package/dist/lib/Persist.spec.js.map +1 -0
  132. package/dist/lib/Session.d.ts +80 -0
  133. package/dist/lib/Session.js +100 -0
  134. package/dist/lib/Session.js.map +1 -0
  135. package/dist/lib/Session.spec.d.ts +1 -0
  136. package/dist/lib/Session.spec.js +43 -0
  137. package/dist/lib/Session.spec.js.map +1 -0
  138. package/dist/lib/ThinQ.d.ts +28 -0
  139. package/dist/lib/ThinQ.js +373 -0
  140. package/dist/lib/ThinQ.js.map +1 -0
  141. package/dist/lib/__tests__/API.spec.d.ts +1 -0
  142. package/dist/lib/__tests__/API.spec.js +55 -0
  143. package/dist/lib/__tests__/API.spec.js.map +1 -0
  144. package/dist/lib/__tests__/Auth.spec.d.ts +1 -0
  145. package/dist/lib/__tests__/Auth.spec.js +110 -0
  146. package/dist/lib/__tests__/Auth.spec.js.map +1 -0
  147. package/dist/lib/__tests__/Device.spec.d.ts +1 -0
  148. package/dist/lib/__tests__/Device.spec.js +53 -0
  149. package/dist/lib/__tests__/Device.spec.js.map +1 -0
  150. package/dist/lib/__tests__/DeviceModel.spec.d.ts +1 -0
  151. package/dist/lib/__tests__/DeviceModel.spec.js +90 -0
  152. package/dist/lib/__tests__/DeviceModel.spec.js.map +1 -0
  153. package/dist/lib/__tests__/Gateway.spec.d.ts +1 -0
  154. package/dist/lib/__tests__/Gateway.spec.js +35 -0
  155. package/dist/lib/__tests__/Gateway.spec.js.map +1 -0
  156. package/dist/lib/__tests__/Persist.spec.d.ts +1 -0
  157. package/dist/lib/__tests__/Persist.spec.js +90 -0
  158. package/dist/lib/__tests__/Persist.spec.js.map +1 -0
  159. package/dist/lib/__tests__/Session.spec.d.ts +1 -0
  160. package/dist/lib/__tests__/Session.spec.js +43 -0
  161. package/dist/lib/__tests__/Session.spec.js.map +1 -0
  162. package/dist/lib/constants.d.ts +95 -0
  163. package/dist/lib/constants.js +106 -0
  164. package/dist/lib/constants.js.map +1 -0
  165. package/dist/lib/request.d.ts +2 -0
  166. package/dist/lib/request.js +66 -0
  167. package/dist/lib/request.js.map +1 -0
  168. package/dist/platform.d.ts +41 -0
  169. package/dist/platform.js +229 -0
  170. package/dist/platform.js.map +1 -0
  171. package/dist/settings.d.ts +8 -0
  172. package/dist/settings.js +9 -0
  173. package/dist/settings.js.map +1 -0
  174. package/dist/status/BaseStatus.d.ts +48 -0
  175. package/dist/status/BaseStatus.js +59 -0
  176. package/dist/status/BaseStatus.js.map +1 -0
  177. package/dist/types/snapshots.d.ts +142 -0
  178. package/dist/types/snapshots.js +6 -0
  179. package/dist/types/snapshots.js.map +1 -0
  180. package/dist/utils/__tests__/normalize.spec.d.ts +1 -0
  181. package/dist/utils/__tests__/normalize.spec.js +95 -0
  182. package/dist/utils/__tests__/normalize.spec.js.map +1 -0
  183. package/dist/utils/normalize.d.ts +22 -0
  184. package/dist/utils/normalize.js +51 -0
  185. package/dist/utils/normalize.js.map +1 -0
  186. package/dist/v1/__tests__/prepareControlData.spec.d.ts +1 -0
  187. package/dist/v1/__tests__/prepareControlData.spec.js +48 -0
  188. package/dist/v1/__tests__/prepareControlData.spec.js.map +1 -0
  189. package/dist/v1/devices/AC.d.ts +13 -0
  190. package/dist/v1/devices/AC.js +112 -0
  191. package/dist/v1/devices/AC.js.map +1 -0
  192. package/dist/v1/devices/AirPurifier.d.ts +15 -0
  193. package/dist/v1/devices/AirPurifier.js +57 -0
  194. package/dist/v1/devices/AirPurifier.js.map +1 -0
  195. package/dist/v1/devices/RangeHood.d.ts +6 -0
  196. package/dist/v1/devices/RangeHood.js +12 -0
  197. package/dist/v1/devices/RangeHood.js.map +1 -0
  198. package/dist/v1/devices/Refrigerator.d.ts +17 -0
  199. package/dist/v1/devices/Refrigerator.js +69 -0
  200. package/dist/v1/devices/Refrigerator.js.map +1 -0
  201. package/dist/v1/devices/Washer.d.ts +10 -0
  202. package/dist/v1/devices/Washer.js +23 -0
  203. package/dist/v1/devices/Washer.js.map +1 -0
  204. package/dist/v1/devices/index.d.ts +6 -0
  205. package/dist/v1/devices/index.js +7 -0
  206. package/dist/v1/devices/index.js.map +1 -0
  207. package/dist/v1/helper.d.ts +14 -0
  208. package/dist/v1/helper.js +111 -0
  209. package/dist/v1/helper.js.map +1 -0
  210. package/dist/v1/transforms/AirPurifierState.d.ts +2 -0
  211. package/dist/v1/transforms/AirPurifierState.js +9 -0
  212. package/dist/v1/transforms/AirPurifierState.js.map +1 -0
  213. package/dist/v1/transforms/AirState.d.ts +9 -0
  214. package/dist/v1/transforms/AirState.js +55 -0
  215. package/dist/v1/transforms/AirState.js.map +1 -0
  216. package/dist/v1/transforms/HoodState.d.ts +17 -0
  217. package/dist/v1/transforms/HoodState.js +20 -0
  218. package/dist/v1/transforms/HoodState.js.map +1 -0
  219. package/dist/v1/transforms/RefState.d.ts +6 -0
  220. package/dist/v1/transforms/RefState.js +29 -0
  221. package/dist/v1/transforms/RefState.js.map +1 -0
  222. package/dist/v1/transforms/WasherDryer.d.ts +49 -0
  223. package/dist/v1/transforms/WasherDryer.js +56 -0
  224. package/dist/v1/transforms/WasherDryer.js.map +1 -0
  225. package/docs/authorization.md +40 -0
  226. package/docs/device-configuration.md +68 -0
  227. package/homebridge-ui/public/index.html +120 -0
  228. package/homebridge-ui/public/js/app.js +300 -0
  229. package/homebridge-ui/public/js/countries.js +233 -0
  230. package/homebridge-ui/public/styles.css +185 -0
  231. package/homebridge-ui/server.js +103 -0
  232. package/jest.config.ts +39 -0
  233. package/package.json +83 -0
  234. package/sample/README.md +10 -0
  235. package/sample/airconditioner-model.json +3080 -0
  236. package/sample/airconditioner-snapshot.json +49 -0
  237. package/sample/airconditioner.json +157 -0
  238. package/sample/dishwasher-model.json +869 -0
  239. package/sample/dishwasher.json +125 -0
  240. package/sample/washer_dryer-model.json +1294 -0
  241. package/sample/washer_dryer.json +126 -0
@@ -0,0 +1,740 @@
1
+ import { BaseDevice } from '../baseDevice.js';
2
+ import { normalizeNumber } from '../helper.js';
3
+ import { WasherDryerStatus } from './WasherDryer.js';
4
+ import { SIX_HOURS_IN_SECONDS, TEN_MINUTES_MS, ONE_HOUR_IN_SECONDS, SIX_MINUTES_MS, DISHWASHER_STANDBY_INTERVAL_MS } from '../lib/constants.js';
5
+ export default class Dishwasher extends BaseDevice {
6
+ platform;
7
+ accessory;
8
+ isRunning = false;
9
+ inputID = 1;
10
+ rinseLevel = 'LEVEL_2';
11
+ inputName = 'Dishwasher Status';
12
+ inputNameOptions = 'Dishwasher Options';
13
+ inputNameRinse = 'Dishwasher Rinse Aid Level';
14
+ inputNameMachine = 'Dishwasher Cleanness Status';
15
+ courseStartString = 'Cycle Start Time Not Set';
16
+ courseTimeString = 'Cycle Duration Not Set';
17
+ courseTimeEndString = 'Cycle End Time Not Set';
18
+ showTime = false;
19
+ firstTime = true;
20
+ firstEnd = true;
21
+ settingDuration = 0;
22
+ dryCounter = 0;
23
+ delayTime = 0;
24
+ firstDelay = true;
25
+ firstStandby = true;
26
+ standbyTimetMS = 0;
27
+ finishedTime = 'Today';
28
+ serviceDishwasher;
29
+ serviceDoorOpened;
30
+ serviceEventFinished;
31
+ tvService;
32
+ dishwasherState;
33
+ dishwasherOptions;
34
+ startTime;
35
+ courseDuration;
36
+ endTime;
37
+ dishwasherRinseLevel;
38
+ dishwasherCleanliness;
39
+ createInputSourceService(name, subtype, identifier, configuredName, isShow) {
40
+ return this.accessory.getService(name) ||
41
+ this.accessory.addService(this.platform.Service.InputSource, name, subtype)
42
+ .setCharacteristic(this.platform.Characteristic.Identifier, identifier)
43
+ .setCharacteristic(this.platform.Characteristic.ConfiguredName, configuredName)
44
+ .setCharacteristic(this.platform.Characteristic.IsConfigured, this.platform.Characteristic.IsConfigured.CONFIGURED)
45
+ .setCharacteristic(this.platform.Characteristic.InputSourceType, this.platform.Characteristic.InputSourceType.APPLICATION)
46
+ .setCharacteristic(this.platform.Characteristic.TargetVisibilityState, isShow ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN)
47
+ .setCharacteristic(this.platform.Characteristic.CurrentVisibilityState, isShow ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
48
+ }
49
+ constructor(platform, accessory, logger) {
50
+ super(platform, accessory, logger);
51
+ this.platform = platform;
52
+ this.accessory = accessory;
53
+ const { Service: { Valve, ContactSensor, OccupancySensor, }, Characteristic, } = this.platform;
54
+ const device = accessory.context.device;
55
+ this.tvService = this.accessory.getService(this.config.name) ||
56
+ this.accessory.addService(this.platform.Service.Television, this.config.name, 'CataNicoGaTa-70');
57
+ this.tvService.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'LG Dishwasher');
58
+ this.tvService.setPrimaryService(true);
59
+ this.tvService.setCharacteristic(this.platform
60
+ .Characteristic.SleepDiscoveryMode, this.platform.Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE);
61
+ this.tvService.getCharacteristic(this.platform.Characteristic.Active)
62
+ .onSet(this.setActive.bind(this))
63
+ .updateValue(this.platform.Characteristic.Active.INACTIVE)
64
+ .onGet(() => {
65
+ return this.onStatus() ? 1 : 0;
66
+ });
67
+ this.tvService
68
+ .setCharacteristic(this.platform.Characteristic.ActiveIdentifier, this.inputID);
69
+ this.tvService
70
+ .getCharacteristic(this.platform.Characteristic.ActiveIdentifier)
71
+ .onSet((inputIdentifier) => {
72
+ const vNum = normalizeNumber(inputIdentifier);
73
+ if (vNum === null) {
74
+ this.logger.error('Dishwasher ActiveIdentifier is not a number');
75
+ return;
76
+ }
77
+ if (vNum > 7 || vNum < 1) {
78
+ this.inputID = 1;
79
+ }
80
+ else {
81
+ this.inputID = vNum;
82
+ }
83
+ })
84
+ .onGet(() => {
85
+ return this.inputID;
86
+ });
87
+ this.dishwasherState = this.createInputSourceService('Dishwasher Status', 'CataNicoGaTa-10030', 1, this.inputName, true);
88
+ this.dishwasherState.getCharacteristic(this.platform.Characteristic.ConfiguredName)
89
+ .onGet(() => {
90
+ this.currentInputName();
91
+ return this.inputName;
92
+ });
93
+ this.tvService.addLinkedService(this.dishwasherState);
94
+ this.dishwasherOptions = this.createInputSourceService('Dishwasher Options', 'CataNicoGaTa-10040', 2, this.inputNameOptions, this.onStatus());
95
+ this.dishwasherOptions.getCharacteristic(this.platform.Characteristic.ConfiguredName)
96
+ .onGet(() => {
97
+ this.currentInputName();
98
+ return this.inputNameOptions;
99
+ });
100
+ this.tvService.addLinkedService(this.dishwasherOptions);
101
+ this.startTime = this.createInputSourceService('Cycle Start Time', 'CataNico-Always10', 3, this.courseStartString, this.showTime);
102
+ this.startTime.getCharacteristic(this.platform.Characteristic.ConfiguredName)
103
+ .onGet(() => {
104
+ return this.courseStartString;
105
+ });
106
+ this.tvService.addLinkedService(this.startTime);
107
+ this.courseDuration = this.createInputSourceService('Cycle Duration', 'CataNico-Always20', 4, this.courseTimeString, this.showTime);
108
+ this.courseDuration.getCharacteristic(this.platform.Characteristic.ConfiguredName)
109
+ .onGet(() => {
110
+ return this.courseTimeString;
111
+ });
112
+ this.tvService.addLinkedService(this.courseDuration);
113
+ this.endTime = this.createInputSourceService('Cycle End Time', 'CataNico-Always30', 5, this.courseTimeEndString, this.showTime);
114
+ this.endTime.getCharacteristic(this.platform.Characteristic.ConfiguredName)
115
+ .onGet(() => {
116
+ return this.courseTimeEndString;
117
+ });
118
+ this.tvService.addLinkedService(this.endTime);
119
+ this.dishwasherRinseLevel = this.createInputSourceService('Dishwasher Rinse Aid Level', 'CataNicoGaTa-10050', 6, this.inputNameRinse, this.onStatus());
120
+ this.dishwasherRinseLevel.getCharacteristic(this.platform.Characteristic.ConfiguredName)
121
+ .onGet(() => {
122
+ this.updateRinseLevel();
123
+ return this.inputNameRinse;
124
+ });
125
+ this.tvService.addLinkedService(this.dishwasherRinseLevel);
126
+ this.dishwasherCleanliness = this.createInputSourceService('Dishwasher Cleanness Status', 'CataNicoGaTa-10060', 7, this.inputNameMachine, this.onStatus());
127
+ this.dishwasherCleanliness.getCharacteristic(this.platform.Characteristic.ConfiguredName)
128
+ .onGet(() => {
129
+ this.updateRinseLevel();
130
+ return this.inputNameMachine;
131
+ });
132
+ this.tvService.addLinkedService(this.dishwasherCleanliness);
133
+ this.serviceDishwasher = accessory.getService(Valve) || accessory.addService(Valve, 'LG Dishwasher');
134
+ this.serviceDishwasher.setCharacteristic(Characteristic.Name, device.name);
135
+ this.serviceDishwasher.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName);
136
+ this.serviceDishwasher.setCharacteristic(this.platform.Characteristic.ConfiguredName, device.name);
137
+ this.serviceDishwasher.setCharacteristic(Characteristic.ValveType, Characteristic.ValveType.IRRIGATION);
138
+ this.serviceDishwasher.getCharacteristic(Characteristic.Active)
139
+ .onSet(this.setActive.bind(this))
140
+ .updateValue(Characteristic.Active.INACTIVE)
141
+ .onGet(() => {
142
+ return this.timerStatus();
143
+ });
144
+ this.serviceDishwasher.setCharacteristic(Characteristic.InUse, Characteristic.InUse.NOT_IN_USE);
145
+ this.serviceDishwasher.getCharacteristic(this.platform.Characteristic.StatusFault)
146
+ .onGet(this.getRinseLevel.bind(this));
147
+ this.serviceDishwasher.getCharacteristic(Characteristic.RemainingDuration).setProps({
148
+ maxValue: SIX_HOURS_IN_SECONDS,
149
+ });
150
+ this.serviceDishwasher.getCharacteristic(this.platform.Characteristic.SetDuration)
151
+ .onGet(() => {
152
+ return this.settingDuration;
153
+ })
154
+ .setProps({
155
+ maxValue: SIX_HOURS_IN_SECONDS,
156
+ });
157
+ // Door open state
158
+ this.serviceDoorOpened = accessory.getService(ContactSensor) || accessory.addService(ContactSensor, 'Dishwasher Door');
159
+ this.serviceDoorOpened.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName);
160
+ this.serviceDoorOpened.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Dishwasher Door');
161
+ this.serviceDoorOpened.getCharacteristic(this.platform.Characteristic.StatusActive)
162
+ .onGet(this.getDoorStatus.bind(this));
163
+ this.serviceDoorOpened.getCharacteristic(this.platform.Characteristic.BatteryLevel)
164
+ .onGet(this.getRinseLevelPercent.bind(this));
165
+ this.serviceDoorOpened.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
166
+ .onGet(this.getRinseLevelStatus.bind(this));
167
+ this.serviceEventFinished = accessory.getService(OccupancySensor);
168
+ if (this.config.dishwasher_trigger) {
169
+ this.serviceEventFinished = this.serviceEventFinished || accessory.addService(OccupancySensor, device.name + ' - Program Finished');
170
+ this.serviceEventFinished.updateCharacteristic(Characteristic.OccupancyDetected, Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED);
171
+ }
172
+ else if (this.serviceEventFinished) {
173
+ accessory.removeService(this.serviceEventFinished);
174
+ }
175
+ }
176
+ currentInputName() {
177
+ if (!this.Status.data.process.includes('RESERVED')) {
178
+ this.firstDelay = true;
179
+ }
180
+ if (!this.Status.data.state.includes('STAND')) {
181
+ this.standbyTimetMS = 0;
182
+ this.firstStandby = true;
183
+ }
184
+ if (this.firstDelay) {
185
+ if (this.Status.data.state.includes('OFF')) {
186
+ this.inputName = 'Power Off';
187
+ this.firstEnd = true;
188
+ this.resetTimeSettings();
189
+ this.settingDuration = 0;
190
+ this.dryCounter = 0;
191
+ }
192
+ else if (this.Status.data.state.includes('STAND')) {
193
+ this.firstEnd = true;
194
+ this.resetTimeSettings();
195
+ this.dryCounter = 0;
196
+ if (!this.onStatus()) {
197
+ this.inputName = 'Power Off';
198
+ }
199
+ else {
200
+ this.inputName = 'In Standby';
201
+ if (!this.Status.data.door.includes('OPEN')) {
202
+ this.inputName += ' (Door Closed)';
203
+ }
204
+ }
205
+ if (this.firstStandby) {
206
+ const standbyTime = new Date();
207
+ this.standbyTimetMS = standbyTime.getTime();
208
+ this.firstStandby = false;
209
+ setTimeout(() => {
210
+ this.serviceDishwasher.updateCharacteristic(this.platform.Characteristic.Active, this.timerStatus());
211
+ this.tvService.updateCharacteristic(this.platform.Characteristic.Active, this.onStatus() ? 1 : 0);
212
+ this.serviceDoorOpened.updateCharacteristic(this.platform.Characteristic.StatusActive, this.onStatus());
213
+ }, DISHWASHER_STANDBY_INTERVAL_MS);
214
+ }
215
+ }
216
+ else if (this.Status.data.state.includes('INITIAL')) {
217
+ this.inputName = 'Initializing';
218
+ this.resetTimeSettings();
219
+ }
220
+ else if (this.Status.data.state.includes('RUNNING')) {
221
+ if (this.Status.data.course.includes('AUTO')) {
222
+ this.inputName = 'Running a Auto Cycle';
223
+ }
224
+ else if (this.Status.data.course.includes('HEAVY')) {
225
+ this.inputName = 'Running a Heavy Cycle';
226
+ }
227
+ else if (this.Status.data.course.includes('DELICATE')) {
228
+ this.inputName = 'Running a Delicate Cycle';
229
+ }
230
+ else if (this.Status.data.course.includes('TURBO')) {
231
+ this.inputName = 'Running a Turbo Cycle';
232
+ }
233
+ else if (this.Status.data.course.includes('NORMAL')) {
234
+ this.inputName = 'Running a Normal Cycle';
235
+ }
236
+ else if (this.Status.data.course.includes('RINSE')) {
237
+ this.inputName = 'Running a Rinse Cycle';
238
+ }
239
+ else if (this.Status.data.course.includes('REFRESH')) {
240
+ this.inputName = 'Running a Refresh Cycle';
241
+ }
242
+ else if (this.Status.data.course.includes('EXPRESS')) {
243
+ this.inputName = 'Running a Express Cycle';
244
+ }
245
+ else if (this.Status.data.course.includes('CLEAN')) {
246
+ this.inputName = 'Cleaning the Dishwasher';
247
+ }
248
+ else if (this.Status.data.course.includes('SHORT')) {
249
+ this.inputName = 'Running a Short Cycle';
250
+ }
251
+ else if (this.Status.data.course.includes('DOWNLOAD')) {
252
+ let downloadCourse = this.Status.data.currentDownloadCourse;
253
+ downloadCourse = downloadCourse.toLocaleLowerCase();
254
+ const downloadCourseCap = downloadCourse.charAt(0).toUpperCase()
255
+ + downloadCourse.slice(1);
256
+ this.inputName = 'Running a ' + downloadCourseCap + ' Cycle';
257
+ }
258
+ else if (this.Status.data.course.includes('QUICK')) {
259
+ this.inputName = 'Running a Quick Cycle';
260
+ }
261
+ else if (this.Status.data.course.includes('STREAM')) {
262
+ this.inputName = 'Ruuning a Stream Cycle';
263
+ }
264
+ else if (this.Status.data.course.includes('SPRAY')) {
265
+ this.inputName = 'Running a Spray Cycle';
266
+ }
267
+ else if (this.Status.data.course.includes('ECO')) {
268
+ this.inputName = 'Running an Eco Cycle';
269
+ }
270
+ else {
271
+ let lowerCase = this.Status.data.course;
272
+ lowerCase = lowerCase.toLocaleLowerCase();
273
+ const upperCase = lowerCase.charAt(0).toUpperCase()
274
+ + lowerCase.slice(1);
275
+ this.inputName = 'Running a ' + upperCase + ' Cycle';
276
+ }
277
+ }
278
+ else if (this.Status.data.state.includes('PAUSE')) {
279
+ this.inputName = 'Paused Cleaning';
280
+ this.firstTime = true;
281
+ this.firstDelay = true;
282
+ }
283
+ else if (this.Status.data.state.includes('END')) {
284
+ if (this.firstEnd) {
285
+ const courseFinished = new Date();
286
+ this.finishedTime = courseFinished.toLocaleString('en-US', {
287
+ weekday: 'short',
288
+ year: 'numeric',
289
+ month: 'short',
290
+ day: 'numeric',
291
+ hour12: false,
292
+ hour: 'numeric',
293
+ minute: 'numeric',
294
+ second: 'numeric',
295
+ timeZoneName: 'short',
296
+ });
297
+ this.firstEnd = false;
298
+ this.resetTimeSettings();
299
+ }
300
+ this.inputName = 'Finished Cycle ' + this.finishedTime;
301
+ if (this.Status.data.extraDry.includes('ON') && this.dryCounter > 3 && this.Status.remainDuration === ONE_HOUR_IN_SECONDS) {
302
+ this.inputName += ' (Waiting For Extra Dry Step)';
303
+ }
304
+ }
305
+ else if (this.Status.data.state.includes('FAIL')) {
306
+ this.inputName = 'Failure Detected';
307
+ }
308
+ else if (this.Status.data.state.includes('RESERVED')) {
309
+ this.inputName = 'Is Reserved';
310
+ }
311
+ else if (this.Status.data.state.includes('RINSING')) {
312
+ this.inputName = 'Rinsing';
313
+ }
314
+ else if (this.Status.data.state.includes('DRYING')) {
315
+ this.inputName = 'Drying';
316
+ }
317
+ else if (this.Status.data.state.includes('NIGHT')) {
318
+ this.inputName = 'Night Drying';
319
+ }
320
+ else if (this.Status.data.state.includes('CANCEL')) {
321
+ this.inputName = 'Cancelled Cleaning';
322
+ }
323
+ else if (this.Status.data.state.includes('ERROR')) {
324
+ this.inputName = 'Cleaning Error';
325
+ }
326
+ else {
327
+ let lowerCase = this.Status.data.state;
328
+ lowerCase = lowerCase.toLocaleLowerCase();
329
+ const upperCase = lowerCase.charAt(0).toUpperCase()
330
+ + lowerCase.slice(1);
331
+ this.inputName = 'Dishwasher ' + upperCase;
332
+ }
333
+ if (this.Status.data.door.includes('OPEN')) {
334
+ this.inputName += ' (Door Open)';
335
+ this.resetTimeSettings();
336
+ }
337
+ if (this.Status.data.state === this.Status.data.process && this.Status.data.process.includes('RUNNING')) {
338
+ this.inputName += '. Step: Cleaning';
339
+ }
340
+ if (this.Status.data.state !== this.Status.data.process && !this.Status.data.process.includes('NONE') && !this.Status.data.state.includes('END')) {
341
+ if (this.Status.data.process.includes('RINSING')) {
342
+ this.inputName += '. Step: Rinsing';
343
+ }
344
+ else if (this.Status.data.process.includes('DRYING')) {
345
+ this.inputName += '. Step: Drying';
346
+ if (this.Status.data.extraDry.includes('ON') && this.dryCounter > 3) {
347
+ this.inputName += ' (Extra)';
348
+ }
349
+ }
350
+ else if (this.Status.data.process.includes('NIGHT')) {
351
+ this.inputName += '. Step: Night Drying';
352
+ }
353
+ else if (this.Status.data.process.includes('END')) {
354
+ this.inputName += '. Step: Ending';
355
+ }
356
+ else if (this.Status.data.process.includes('CANCEL')) {
357
+ this.inputName += '. Step: Cancelling';
358
+ }
359
+ else if (this.Status.data.process.includes('RESERVED') && this.Status.data.delayStart === 'ON') {
360
+ const courseTime = new Date(0);
361
+ this.delayTime = this.Status.data.reserveTimeHour * 60 * 60 + this.Status.data.reserveTimeMinute * 60;
362
+ courseTime.setSeconds(this.delayTime);
363
+ let delayTimeString = courseTime.toISOString().substr(11, 8);
364
+ if (delayTimeString.startsWith('0')) {
365
+ delayTimeString = delayTimeString.substring(1);
366
+ }
367
+ let hourMinutes = 'Minutes';
368
+ if (this.delayTime > ONE_HOUR_IN_SECONDS) {
369
+ hourMinutes = 'Hours';
370
+ }
371
+ if (this.delayTime === ONE_HOUR_IN_SECONDS) {
372
+ hourMinutes = 'Hour';
373
+ }
374
+ this.inputName += '. Step: Waiting ' + delayTimeString + ' ' + hourMinutes + ' to Start';
375
+ this.timeDurationEnd();
376
+ this.firstDelay = false;
377
+ }
378
+ else {
379
+ if (!this.Status.data.state.includes('INITIAL') && !this.Status.data.state.includes('STAND') && !this.Status.data.process.includes('RESERVED')) {
380
+ let lowerCase = this.Status.data.state;
381
+ lowerCase = lowerCase.toLocaleLowerCase();
382
+ const upperCase = lowerCase.charAt(0).toUpperCase()
383
+ + lowerCase.slice(1);
384
+ this.inputName += '. Step: ' + upperCase;
385
+ }
386
+ }
387
+ }
388
+ }
389
+ this.inputNameOptions = 'Options:';
390
+ if (this.Status.data.energySaver?.includes('ON')) {
391
+ this.inputNameOptions += ' Energy Saver,';
392
+ }
393
+ if (this.Status.data.halfLoad?.includes('ON')) {
394
+ this.inputNameOptions += ' Half Load,';
395
+ }
396
+ if (this.Status.data.dualZone?.includes('ON')) {
397
+ this.inputNameOptions += ' Dual Zone,';
398
+ }
399
+ if (this.Status.data.highTemp?.includes('ON')) {
400
+ this.inputNameOptions += ' High Temp,';
401
+ }
402
+ if (this.Status.data.steam?.includes('ON')) {
403
+ this.inputNameOptions += ' Steam,';
404
+ }
405
+ if (this.Status.data.extraRinse?.includes('ON')) {
406
+ this.inputNameOptions += ' Extra Rinse,';
407
+ }
408
+ if (this.Status.data.extraDry?.includes('ON')) {
409
+ this.inputNameOptions += ' Extra Dry,';
410
+ }
411
+ if (this.Status.data.nightDry?.includes('ON')) {
412
+ this.inputNameOptions += ' Night Dry,';
413
+ }
414
+ if (this.Status.data.delayStart?.includes('ON')) {
415
+ this.inputNameOptions += ' Delay Start,';
416
+ }
417
+ if (!this.Status.data.energySaver?.includes('ON') &&
418
+ !this.Status.data.halfLoad?.includes('ON') &&
419
+ !this.Status.data.dualZone?.includes('ON') &&
420
+ !this.Status.data.highTemp?.includes('ON') &&
421
+ !this.Status.data.steam?.includes('ON') &&
422
+ !this.Status.data.extraRinse?.includes('ON') &&
423
+ !this.Status.data.extraDry?.includes('ON') &&
424
+ !this.Status.data.nightDry?.includes('ON') &&
425
+ !this.Status.data.delayStart?.includes('ON')) {
426
+ this.inputNameOptions += ' None,';
427
+ }
428
+ this.inputNameOptions = this.inputNameOptions.substring(0, this.inputNameOptions.length - 1);
429
+ ///Names length Check
430
+ this.inputName = this.nameLengthCheck(this.inputName);
431
+ this.inputNameOptions = this.nameLengthCheck(this.inputNameOptions);
432
+ //////
433
+ if (this.dishwasherState.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.inputName) {
434
+ this.dishwasherState.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.inputName);
435
+ }
436
+ if (!this.Status.isPowerOn) {
437
+ this.inputNameOptions = 'Dishwasher Options';
438
+ }
439
+ if (this.dishwasherOptions.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.inputNameOptions) {
440
+ this.dishwasherOptions.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.inputNameOptions);
441
+ }
442
+ this.dishwasherOptions.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.onStatus() ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
443
+ this.dishwasherOptions.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.onStatus() ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
444
+ }
445
+ timeDurationEnd() {
446
+ /////Cycle duration
447
+ this.showTime = true;
448
+ const courseTime = new Date(0);
449
+ courseTime.setSeconds(this.Status.remainDuration);
450
+ let courseTimeString = courseTime.toISOString().substr(11, 8);
451
+ if (courseTimeString.startsWith('0')) {
452
+ courseTimeString = courseTimeString.substring(1);
453
+ }
454
+ let hourMinutes = 'Minutes';
455
+ if (this.Status.remainDuration > ONE_HOUR_IN_SECONDS) {
456
+ hourMinutes = 'Hours';
457
+ }
458
+ if (this.Status.remainDuration === ONE_HOUR_IN_SECONDS) {
459
+ hourMinutes = 'Hour';
460
+ }
461
+ this.courseTimeString = 'Duration: ' + courseTimeString + ' ' + hourMinutes;
462
+ if (this.Status.data.extraDry.includes('ON')) {
463
+ this.courseTimeString += ' + 1:00:00 Hour For Extra Dry';
464
+ }
465
+ ////Starting time
466
+ const courseCurrentTime = new Date();
467
+ const courseStartMS = courseCurrentTime.getTime();
468
+ const courseStart = new Date(courseStartMS + this.delayTime * 1000);
469
+ const newDate = courseStart.toLocaleString('en-US', {
470
+ weekday: 'long',
471
+ year: 'numeric',
472
+ month: 'long',
473
+ day: 'numeric',
474
+ hour12: false,
475
+ hour: 'numeric',
476
+ minute: 'numeric',
477
+ second: 'numeric',
478
+ timeZoneName: 'short',
479
+ });
480
+ this.courseStartString = 'Start: ' + newDate;
481
+ const dateEnd = new Date(this.Status.remainDuration * 1000 + courseStartMS + this.delayTime * 1000);
482
+ const newEndDate = dateEnd.toLocaleString('en-US', {
483
+ weekday: 'long',
484
+ year: 'numeric',
485
+ month: 'long',
486
+ day: 'numeric',
487
+ hour12: false,
488
+ hour: 'numeric',
489
+ minute: 'numeric',
490
+ second: 'numeric',
491
+ timeZoneName: 'short',
492
+ });
493
+ this.courseTimeEndString = 'End: ' + newEndDate;
494
+ ///Names length Check
495
+ this.courseStartString = this.nameLengthCheck(this.courseStartString);
496
+ this.courseTimeString = this.nameLengthCheck(this.courseTimeString);
497
+ this.courseTimeEndString = this.nameLengthCheck(this.courseTimeEndString);
498
+ //////
499
+ if (this.startTime.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.courseStartString) {
500
+ this.startTime.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.courseStartString);
501
+ }
502
+ if (this.courseDuration.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.courseTimeString) {
503
+ this.courseDuration.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.courseTimeString);
504
+ }
505
+ if (this.endTime.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.courseTimeEndString) {
506
+ this.endTime.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.courseTimeEndString);
507
+ }
508
+ this.startTime.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
509
+ this.startTime.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
510
+ this.courseDuration.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
511
+ this.courseDuration.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
512
+ this.endTime.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
513
+ this.endTime.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
514
+ }
515
+ setActive() {
516
+ this.logger.debug('Dishwasher Response', this.Status.data);
517
+ // this.platform.log('Dishwasher rinse', this.Status.data.rinseLevel);
518
+ // this.platform.log('Dishwasher rinse typeof', typeof this.Status.data.rinseLevel);
519
+ //this.updateRinseLevel();
520
+ // this.platform.log('Dishwasher rinse status', this.rinseStatus);
521
+ // this.serviceDishwasher.updateCharacteristic(this.platform.Characteristic.StatusFault, this.rinseStatus);
522
+ // this.platform.log('Dishwasher Response', this.Status);
523
+ // throw new this.platform.api.hap.HapStatusError(-70412 /* this.platform.api.hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE */);
524
+ }
525
+ updateAccessoryCharacteristic(device) {
526
+ super.updateAccessoryCharacteristic(device);
527
+ const { Characteristic } = this.platform;
528
+ if (this.Status.remainDuration !== this.serviceDishwasher.getCharacteristic(Characteristic.RemainingDuration).value) {
529
+ if (this.Status.data.extraDry.includes('ON') && this.Status.remainDuration === 3600) {
530
+ this.dryCounter += 1;
531
+ }
532
+ if (this.dryCounter <= 3) {
533
+ this.serviceDishwasher.updateCharacteristic(Characteristic.RemainingDuration, this.Status.remainDuration);
534
+ }
535
+ }
536
+ if (this.Status.isPowerOn) {
537
+ this.settingDuration = this.Status.data.initialTimeHour * 60 * 60 + this.Status.data.initialTimeMinute * 60;
538
+ }
539
+ if (this.settingDuration !== this.serviceDishwasher.getCharacteristic(Characteristic.SetDuration).value) {
540
+ this.serviceDishwasher.updateCharacteristic(this.platform.Characteristic.SetDuration, this.settingDuration);
541
+ }
542
+ this.serviceDishwasher.updateCharacteristic(Characteristic.Active, this.timerStatus());
543
+ this.tvService.updateCharacteristic(this.platform.Characteristic.Active, this.onStatus() ? 1 : 0);
544
+ if (this.Status.data.delayStart === 'ON' && this.Status.data.process.includes('RESER')) {
545
+ this.serviceDishwasher.updateCharacteristic(Characteristic.InUse, 0);
546
+ }
547
+ else if (this.Status.data.state.includes('STAND')) {
548
+ this.serviceDishwasher.updateCharacteristic(Characteristic.InUse, 0);
549
+ }
550
+ else {
551
+ this.serviceDishwasher.updateCharacteristic(Characteristic.InUse, this.Status.isRunning ? 1 : 0);
552
+ }
553
+ if (this.serviceDoorOpened) {
554
+ const contactSensorValue = this.Status.isDoorClosed ?
555
+ Characteristic.ContactSensorState.CONTACT_DETECTED : Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
556
+ this.serviceDoorOpened.updateCharacteristic(Characteristic.ContactSensorState, contactSensorValue);
557
+ }
558
+ this.currentInputName();
559
+ if (this.Status.data.state.includes('RUNNING') && !this.Status.data.process.includes('RESERVED') && this.firstTime) {
560
+ this.delayTime = 0;
561
+ this.timeDurationEnd();
562
+ this.firstTime = false;
563
+ }
564
+ this.updateRinseLevel();
565
+ }
566
+ get Status() {
567
+ return new DishwasherStatus(this.accessory.context.device.snapshot?.dishwasher, this.accessory.context.device.deviceModel);
568
+ }
569
+ get config() {
570
+ return Object.assign({}, {
571
+ dishwasher_trigger: false,
572
+ }, super.config);
573
+ }
574
+ nameLengthCheck(newName) {
575
+ if (newName.length >= 64) {
576
+ newName = newName.slice(0, 60) + '...';
577
+ }
578
+ return newName;
579
+ }
580
+ updateRinseLevel() {
581
+ if (this.Status.data.state.includes('RUNNING')) {
582
+ this.rinseLevel = this.Status.data.rinseLevel || 'LEVEL_1';
583
+ }
584
+ let rinseLevelPercent = 100;
585
+ let rinseLevelStatus = 0;
586
+ if (this.rinseLevel === 'LEVEL_0') {
587
+ rinseLevelPercent = 0;
588
+ rinseLevelStatus = 1;
589
+ this.inputNameRinse = 'Rinse Aid Level is Running Low';
590
+ this.inputID = 3;
591
+ }
592
+ else if (this.rinseLevel === 'LEVEL_1') {
593
+ rinseLevelPercent = 50;
594
+ this.inputNameRinse = 'Rinse Aid Level is at 50% Capacity';
595
+ }
596
+ else if (this.rinseLevel === 'LEVEL_2') {
597
+ rinseLevelPercent = 100;
598
+ this.inputNameRinse = 'Rinse Aid Level is at 100% Capacity';
599
+ }
600
+ else {
601
+ this.inputNameRinse = 'Rinse Aid Level is Normal';
602
+ }
603
+ this.serviceDishwasher.updateCharacteristic(this.platform.Characteristic.StatusFault, rinseLevelStatus);
604
+ this.serviceDoorOpened.updateCharacteristic(this.platform.Characteristic.StatusActive, this.onStatus());
605
+ this.serviceDoorOpened.updateCharacteristic(this.platform.Characteristic.BatteryLevel, rinseLevelPercent);
606
+ this.serviceDoorOpened.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, rinseLevelStatus);
607
+ if (this.Status.data.tclCount > 30) {
608
+ this.inputID = 7;
609
+ this.inputNameMachine = 'Machine Cleaning Cycle is Needed Soon';
610
+ if (this.dishwasherCleanliness.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.inputNameMachine) {
611
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.inputNameMachine);
612
+ }
613
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.onStatus() ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
614
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.onStatus() ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
615
+ }
616
+ else {
617
+ this.inputNameMachine = 'Dishwasher is Clean';
618
+ if (this.dishwasherCleanliness.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.inputNameMachine) {
619
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.inputNameMachine);
620
+ }
621
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.platform.Characteristic.TargetVisibilityState.HIDDEN);
622
+ this.dishwasherCleanliness.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
623
+ }
624
+ if (this.dishwasherRinseLevel.getCharacteristic(this.platform.Characteristic.ConfiguredName).value !== this.inputNameRinse) {
625
+ this.dishwasherRinseLevel.updateCharacteristic(this.platform.Characteristic.ConfiguredName, this.inputNameRinse);
626
+ }
627
+ this.dishwasherRinseLevel.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.onStatus() ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
628
+ this.dishwasherRinseLevel.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.onStatus() ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
629
+ }
630
+ onStatus() {
631
+ const newCurrentTime = new Date();
632
+ const newCurrentTimeMS = newCurrentTime.getTime();
633
+ if (this.standbyTimetMS !== 0) {
634
+ if (newCurrentTimeMS - this.standbyTimetMS > SIX_MINUTES_MS) {
635
+ return false;
636
+ }
637
+ else {
638
+ return this.Status.isPowerOn;
639
+ }
640
+ }
641
+ else {
642
+ return this.Status.isPowerOn;
643
+ }
644
+ }
645
+ timerStatus() {
646
+ if (!this.onStatus || this.Status.remainDuration === 0 || this.Status.data.state.includes('STAND')) {
647
+ return 0;
648
+ }
649
+ else {
650
+ return 1;
651
+ }
652
+ }
653
+ getRinseLevel() {
654
+ if (this.Status.data.state.includes('RUNNING')) {
655
+ this.rinseLevel = this.Status.data.rinseLevel || 'LEVEL_1';
656
+ }
657
+ let rinseStatus = 0;
658
+ if (this.rinseLevel === 'LEVEL_0') {
659
+ rinseStatus = 1;
660
+ }
661
+ return rinseStatus;
662
+ }
663
+ getDoorStatus() {
664
+ return this.onStatus();
665
+ }
666
+ getRinseLevelPercent() {
667
+ let levelPercent = this.rinseLevel;
668
+ if (this.Status.data.state.includes('RUNNING')) {
669
+ levelPercent = this.Status.data.rinseLevel || 'LEVEL_1';
670
+ }
671
+ let rinseLevelPercent = 100;
672
+ if (levelPercent === 'LEVEL_0') {
673
+ rinseLevelPercent = 0;
674
+ }
675
+ else if (levelPercent === 'LEVEL_1') {
676
+ rinseLevelPercent = 50;
677
+ }
678
+ return rinseLevelPercent;
679
+ }
680
+ getRinseLevelStatus() {
681
+ let levelStatus = this.rinseLevel;
682
+ if (this.Status.data.state.includes('RUNNING')) {
683
+ levelStatus = this.Status.data.rinseLevel || 'LEVEL_1';
684
+ }
685
+ let rinseLevelStatus = 0;
686
+ if (levelStatus === 'LEVEL_0') {
687
+ rinseLevelStatus = 1;
688
+ }
689
+ return rinseLevelStatus;
690
+ }
691
+ resetTimeSettings() {
692
+ this.showTime = false;
693
+ this.firstTime = true;
694
+ this.firstDelay = true;
695
+ this.courseStartString = 'Cycle Start Time Not Set';
696
+ this.courseTimeString = 'Cycle Duration Not Set';
697
+ this.courseTimeEndString = 'Cycle End Time Not Set';
698
+ this.startTime.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
699
+ this.startTime.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
700
+ this.courseDuration.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
701
+ this.courseDuration.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
702
+ this.endTime.updateCharacteristic(this.platform.Characteristic.TargetVisibilityState, this.showTime ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN);
703
+ this.endTime.updateCharacteristic(this.platform.Characteristic.CurrentVisibilityState, this.showTime ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN);
704
+ }
705
+ update(snapshot) {
706
+ super.update(snapshot);
707
+ const dishwasher = snapshot.dishwasher;
708
+ if (!dishwasher) {
709
+ return;
710
+ }
711
+ // when washer state is changed
712
+ if (this.config.dishwasher_trigger && this.serviceEventFinished && 'state' in dishwasher) {
713
+ const { Characteristic: { OccupancyDetected, }, } = this.platform;
714
+ // detect if washer program in done
715
+ if ((['END'].includes(dishwasher.state)) || (this.isRunning && !this.Status.isRunning)) {
716
+ this.serviceEventFinished.updateCharacteristic(OccupancyDetected, OccupancyDetected.OCCUPANCY_DETECTED);
717
+ this.isRunning = false; // marked device as not running
718
+ // turn it off after 10 minute
719
+ setTimeout(() => {
720
+ this.serviceEventFinished?.updateCharacteristic(OccupancyDetected, OccupancyDetected.OCCUPANCY_NOT_DETECTED);
721
+ }, TEN_MINUTES_MS);
722
+ }
723
+ // detect if dishwasher program is start
724
+ if (this.Status.isRunning && !this.isRunning) {
725
+ this.serviceEventFinished.updateCharacteristic(OccupancyDetected, OccupancyDetected.OCCUPANCY_NOT_DETECTED);
726
+ this.isRunning = true;
727
+ }
728
+ }
729
+ }
730
+ }
731
+ // re-use some status in washer
732
+ export class DishwasherStatus extends WasherDryerStatus {
733
+ get isRunning() {
734
+ return this.isPowerOn && this.data?.state === this.deviceModel.lookupMonitorName('state', '@DW_STATE_RUNNING_W');
735
+ }
736
+ get isDoorClosed() {
737
+ return this.data?.door === this.deviceModel.lookupMonitorName('door', '@CP_OFF_EN_W');
738
+ }
739
+ }
740
+ //# sourceMappingURL=Dishwasher.js.map