@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,111 @@
1
+ import AirState from './transforms/AirState.js';
2
+ import WasherDryer from './transforms/WasherDryer.js';
3
+ import { Washer, AC, Refrigerator, AirPurifier, RangeHood } from './devices/index.js';
4
+ import RefState from './transforms/RefState.js';
5
+ import { randomUUID } from 'crypto';
6
+ import AirPurifierState from './transforms/AirPurifierState.js';
7
+ import HoodState from './transforms/HoodState.js';
8
+ export default class Helper {
9
+ static make(device) {
10
+ switch (device.type) {
11
+ case 'DRYER':
12
+ case 'WASHER': return Washer;
13
+ case 'AC': return AC;
14
+ case 'REFRIGERATOR': return Refrigerator;
15
+ case 'AIR_PURIFIER': return AirPurifier;
16
+ case 'HOOD': return RangeHood;
17
+ }
18
+ return null;
19
+ }
20
+ /**
21
+ * transform device from thinq1 to thinq2 compatible (with snapshot data)
22
+ */
23
+ static transform(device, monitorData) {
24
+ const decodedMonitor = device.deviceModel.decodeMonitor(monitorData || {});
25
+ switch (device.type) {
26
+ case 'DRYER':
27
+ case 'WASHER':
28
+ device.data.snapshot = WasherDryer(device.deviceModel, decodedMonitor);
29
+ break;
30
+ case 'AIR_PURIFIER':
31
+ device.data.snapshot = AirPurifierState(device.deviceModel, decodedMonitor);
32
+ break;
33
+ case 'AC':
34
+ device.data.snapshot = AirState(device.deviceModel, decodedMonitor);
35
+ break;
36
+ case 'REFRIGERATOR':
37
+ device.data.snapshot = RefState(device.deviceModel, decodedMonitor);
38
+ break;
39
+ case 'HOOD':
40
+ device.data.snapshot = HoodState(device.deviceModel, decodedMonitor);
41
+ break;
42
+ default:
43
+ // return original device data if not supported
44
+ return device;
45
+ }
46
+ if (device.data.snapshot) {
47
+ if (monitorData) {
48
+ // mark device online to perform update
49
+ device.data.online = true;
50
+ device.data.snapshot.online = true;
51
+ }
52
+ device.data.snapshot.raw = monitorData === null ? null : decodedMonitor;
53
+ }
54
+ return device;
55
+ }
56
+ static prepareControlData(device, key, value) {
57
+ const data = {
58
+ cmd: 'Control',
59
+ cmdOpt: 'Set',
60
+ deviceId: device.id,
61
+ workId: randomUUID(),
62
+ };
63
+ if (device.deviceModel.data.ControlWifi?.type === 'BINARY(BYTE)') {
64
+ const sampleData = device.deviceModel.data.ControlWifi?.action?.SetControl?.data || '[]';
65
+ const decodedMonitor = device.snapshot.raw || {};
66
+ decodedMonitor[key] = value;
67
+ // build data array of byte (coerce booleans and non-numeric values safely)
68
+ let replaced = sampleData;
69
+ for (const p of Object.keys(decodedMonitor)) {
70
+ const raw = decodedMonitor[p];
71
+ let rep;
72
+ if (raw === null || raw === undefined) {
73
+ rep = '0';
74
+ }
75
+ else if (typeof raw === 'boolean') {
76
+ rep = raw ? '1' : '0';
77
+ }
78
+ else {
79
+ rep = String(raw);
80
+ }
81
+ const num = Number(rep);
82
+ const numVal = Number.isNaN(num) ? 0 : num;
83
+ replaced = replaced.replace(new RegExp('{{' + p + '}}', 'g'), String(numVal));
84
+ }
85
+ const byteArray = new Uint8Array(JSON.parse(replaced));
86
+ Object.assign(data, {
87
+ value: 'ControlData',
88
+ data: Buffer.from(String.fromCharCode(...byteArray)).toString('base64'),
89
+ format: 'B64',
90
+ });
91
+ }
92
+ else {
93
+ data.value = {
94
+ [key]: value,
95
+ };
96
+ data.data = '';
97
+ }
98
+ return data;
99
+ }
100
+ }
101
+ export function lookupEnumIndex(enumType, value) {
102
+ return Object.keys(enumType)[Object.values(enumType).indexOf(value)];
103
+ }
104
+ export function loopupEnum(deviceModel, decodedMonitor, key) {
105
+ if (!(key in decodedMonitor)) {
106
+ return null;
107
+ }
108
+ return deviceModel.enumName(key, decodedMonitor[key]);
109
+ }
110
+ export { normalizeBoolean, normalizeNumber, safeParseInt, safeParseFloat } from '../utils/normalize.js';
111
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../../src/v1/helper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { DeviceModel } from '../../lib/DeviceModel.js';
2
+ export default function AirPurifierState(deviceModel: DeviceModel, decodedMonitor: any): Record<string, any>;
@@ -0,0 +1,9 @@
1
+ import AirState from './AirState.js';
2
+ import { safeParseInt } from '../helper.js';
3
+ export default function AirPurifierState(deviceModel, decodedMonitor) {
4
+ const airState = AirState(deviceModel, decodedMonitor);
5
+ airState['airState.operation'] = !!safeParseInt(decodedMonitor.Operation);
6
+ airState['airState.miscFuncState.airFast'] = !!safeParseInt(decodedMonitor.AirFast);
7
+ return airState;
8
+ }
9
+ //# sourceMappingURL=AirPurifierState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AirPurifierState.js","sourceRoot":"","sources":["../../../src/v1/transforms/AirPurifierState.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,WAAwB,EAAE,cAAmB;IACpF,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAEvD,QAAQ,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1E,QAAQ,CAAC,gCAAgC,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAEpF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { DeviceModel } from '../../lib/DeviceModel.js';
2
+ export declare enum ACOperation {
3
+ OFF = "@AC_MAIN_OPERATION_OFF_W",
4
+ /** This one seems to mean "on" ? */
5
+ RIGHT_ON = "@AC_MAIN_OPERATION_RIGHT_ON_W",
6
+ LEFT_ON = "@AC_MAIN_OPERATION_LEFT_ON_W",
7
+ ALL_ON = "@AC_MAIN_OPERATION_ALL_ON_W"
8
+ }
9
+ export default function AirState(deviceModel: DeviceModel, decodedMonitor: any): Record<string, any>;
@@ -0,0 +1,55 @@
1
+ import { loopupEnum, safeParseInt, safeParseFloat } from '../helper.js';
2
+ export var ACOperation;
3
+ (function (ACOperation) {
4
+ ACOperation["OFF"] = "@AC_MAIN_OPERATION_OFF_W";
5
+ /** This one seems to mean "on" ? */
6
+ ACOperation["RIGHT_ON"] = "@AC_MAIN_OPERATION_RIGHT_ON_W";
7
+ ACOperation["LEFT_ON"] = "@AC_MAIN_OPERATION_LEFT_ON_W";
8
+ ACOperation["ALL_ON"] = "@AC_MAIN_OPERATION_ALL_ON_W";
9
+ })(ACOperation || (ACOperation = {}));
10
+ export default function AirState(deviceModel, decodedMonitor) {
11
+ const airState = {
12
+ 'airState.opMode': safeParseInt(decodedMonitor.OpMode),
13
+ 'airState.operation': loopupEnum(deviceModel, decodedMonitor, 'Operation') !== ACOperation.OFF,
14
+ 'airState.tempState.current': safeParseFloat(decodedMonitor.TempCur),
15
+ 'airState.tempState.target': safeParseFloat(decodedMonitor.TempCfg),
16
+ 'airState.windStrength': safeParseInt(decodedMonitor.WindStrength),
17
+ 'airState.wDir.vStep': safeParseInt(decodedMonitor.WDirVStep),
18
+ 'airState.wDir.hStep': safeParseInt(decodedMonitor.WDirHStep),
19
+ 'airState.circulate.rotate': safeParseInt(decodedMonitor.CirculateDir),
20
+ 'airState.lightingState.signal': safeParseInt(decodedMonitor.SignalLighting),
21
+ 'airState.quality.overall': 0,
22
+ 'airState.quality.sensorMon': 0,
23
+ 'airState.quality.PM1': 0,
24
+ 'airState.energy.onCurrent': 0,
25
+ };
26
+ if (deviceModel.value('TempCur')) {
27
+ airState['airState.tempState.current'] = Math.max(airState['airState.tempState.current'], deviceModel.value('TempCur').min);
28
+ }
29
+ if (deviceModel.value('TempCfg')) {
30
+ airState['airState.tempState.target'] = Math.max(airState['airState.tempState.target'], deviceModel.value('TempCfg').min);
31
+ }
32
+ if (decodedMonitor.TotalAirPolution) {
33
+ airState['airState.quality.overall'] = safeParseInt(decodedMonitor.TotalAirPolution);
34
+ }
35
+ if (decodedMonitor.SensorMon) {
36
+ airState['airState.quality.sensorMon'] = safeParseInt(decodedMonitor.SensorMon);
37
+ }
38
+ if (decodedMonitor.SensorPM1) {
39
+ airState['airState.quality.PM1'] = safeParseInt(decodedMonitor.SensorPM1);
40
+ }
41
+ if (decodedMonitor.SensorPM2) {
42
+ airState['airState.quality.PM2'] = safeParseInt(decodedMonitor.SensorPM2);
43
+ }
44
+ if (decodedMonitor.SensorPM10) {
45
+ airState['airState.quality.PM10'] = safeParseInt(decodedMonitor.SensorPM10);
46
+ }
47
+ if (decodedMonitor.Jet) {
48
+ airState['airState.wMode.jet'] = safeParseInt(decodedMonitor.Jet);
49
+ }
50
+ if (decodedMonitor.SensorHumidity) {
51
+ airState['airState.humidity.current'] = safeParseInt(decodedMonitor.SensorHumidity);
52
+ }
53
+ return airState;
54
+ }
55
+ //# sourceMappingURL=AirState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AirState.js","sourceRoot":"","sources":["../../../src/v1/transforms/AirState.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { DeviceModel } from '../../lib/DeviceModel.js';
2
+ export default function HoodState(deviceModel: DeviceModel, decodedMonitor: any): {
3
+ hoodState: {
4
+ ventMode: string | number | null;
5
+ error: string | number | null;
6
+ ventLevel: number;
7
+ lampSet: any;
8
+ remainTimeMinute: number;
9
+ ventSet: any;
10
+ hoodFotaEnable: string;
11
+ remainTimeSecond: number;
12
+ childLock: string;
13
+ standyMode: string;
14
+ lampLevel: number;
15
+ hoodState: string;
16
+ };
17
+ };
@@ -0,0 +1,20 @@
1
+ import { safeParseInt } from '../helper.js';
2
+ export default function HoodState(deviceModel, decodedMonitor) {
3
+ return {
4
+ hoodState: {
5
+ 'ventMode': deviceModel.enumName('VentMode', decodedMonitor.VentMode),
6
+ 'error': deviceModel.enumName('Error', decodedMonitor.VentMode),
7
+ 'ventLevel': safeParseInt(decodedMonitor.VentLevel),
8
+ 'lampSet': decodedMonitor.LampSet,
9
+ 'remainTimeMinute': safeParseInt(decodedMonitor.TimerMin),
10
+ 'ventSet': decodedMonitor.VentSet,
11
+ 'hoodFotaEnable': safeParseInt(decodedMonitor.FOTAEnable) ? 'ENABLE' : 'DISABLE',
12
+ 'remainTimeSecond': safeParseInt(decodedMonitor.TimerSec),
13
+ 'childLock': safeParseInt(decodedMonitor.ChildLock) ? 'ENABLE' : 'DISABLE',
14
+ 'standyMode': safeParseInt(decodedMonitor.StandyMode) ? 'ENABLE' : 'DISABLE',
15
+ 'lampLevel': safeParseInt(decodedMonitor.LampLevel),
16
+ 'hoodState': safeParseInt(decodedMonitor.HoodState) ? 'USING' : 'INIT',
17
+ },
18
+ };
19
+ }
20
+ //# sourceMappingURL=HoodState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoodState.js","sourceRoot":"","sources":["../../../src/v1/transforms/HoodState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,WAAwB,EAAE,cAAmB;IAC7E,OAAO;QACL,SAAS,EAAE;YACT,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC,QAAQ,CAAC;YACrE,OAAO,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC,QAAQ,CAAC;YAC/D,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC;YACnD,SAAS,EAAE,cAAc,CAAC,OAAO;YACjC,kBAAkB,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC;YACzD,SAAS,EAAE,cAAc,CAAC,OAAO;YACjC,gBAAgB,EAAE,YAAY,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAChF,kBAAkB,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,CAAC;YACzD,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAC1E,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAC5E,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC;YACnD,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;SACvE;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { DeviceModel } from '../../lib/DeviceModel.js';
2
+ export declare enum DoorOpenState {
3
+ OPEN = "OPEN",
4
+ CLOSE = "CLOSE"
5
+ }
6
+ export default function RefState(deviceModel: DeviceModel, decodedMonitor: any): Record<string, any>;
@@ -0,0 +1,29 @@
1
+ import { lookupEnumIndex, loopupEnum, safeParseInt } from '../helper.js';
2
+ export var DoorOpenState;
3
+ (function (DoorOpenState) {
4
+ DoorOpenState["OPEN"] = "OPEN";
5
+ DoorOpenState["CLOSE"] = "CLOSE";
6
+ })(DoorOpenState || (DoorOpenState = {}));
7
+ export default function RefState(deviceModel, decodedMonitor) {
8
+ const snapshot = {
9
+ refState: {
10
+ fridgeTemp: decodedMonitor.TempRefrigerator || deviceModel.default('TempRefrigerator') || '0',
11
+ freezerTemp: decodedMonitor.TempFreezer || deviceModel.default('TempFreezer') || '0',
12
+ atLeastOneDoorOpen: lookupEnumIndex(DoorOpenState, loopupEnum(deviceModel, decodedMonitor, 'DoorOpenState') || deviceModel.default('DoorOpenState')),
13
+ tempUnit: safeParseInt(decodedMonitor.TempUnit || deviceModel.default('TempUnit')) ? 'CELSIUS' : 'FAHRENHEIT',
14
+ },
15
+ };
16
+ snapshot.refState.fridgeTemp = safeParseInt(snapshot.refState.fridgeTemp);
17
+ snapshot.refState.freezerTemp = safeParseInt(snapshot.refState.freezerTemp);
18
+ if ('IcePlus' in decodedMonitor) {
19
+ snapshot.refState.expressMode = decodedMonitor.IcePlus || deviceModel.default('IcePlus') || '0';
20
+ }
21
+ if ('ExpressFridge' in decodedMonitor) {
22
+ snapshot.refState.expressFridge = decodedMonitor.ExpressFridge || deviceModel.default('ExpressFridge') || '0';
23
+ }
24
+ if ('EcoFriendly' in decodedMonitor) {
25
+ snapshot.refState.ecoFriendly = decodedMonitor.EcoFriendly || deviceModel.default('EcoFriendly') || '0';
26
+ }
27
+ return snapshot;
28
+ }
29
+ //# sourceMappingURL=RefState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefState.js","sourceRoot":"","sources":["../../../src/v1/transforms/RefState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,CAAN,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,8BAAa,CAAA;IACb,gCAAe,CAAA;AACjB,CAAC,EAHW,aAAa,KAAb,aAAa,QAGxB;AAED,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,WAAwB,EAAE,cAAmB;IAC5E,MAAM,QAAQ,GAAwB;QACpC,QAAQ,EAAE;YACR,UAAU,EAAE,cAAc,CAAC,gBAAgB,IAAI,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,GAAG;YAC7F,WAAW,EAAE,cAAc,CAAC,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG;YAEpF,kBAAkB,EAAE,eAAe,CAAC,aAAa,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,eAAe,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YACpJ,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,QAAQ,IAAI,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY;SAC9G;KACF,CAAC;IAEF,QAAQ,CAAC,QAAQ,CAAC,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC1E,QAAQ,CAAC,QAAQ,CAAC,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE5E,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QAChC,QAAQ,CAAC,QAAQ,CAAC,WAAW,GAAG,cAAc,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;IAClG,CAAC;IAED,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;QACtC,QAAQ,CAAC,QAAQ,CAAC,aAAa,GAAG,cAAc,CAAC,aAAa,IAAI,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC;IAChH,CAAC;IAED,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;QACpC,QAAQ,CAAC,QAAQ,CAAC,WAAW,GAAG,cAAc,CAAC,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC;IAC1G,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { DeviceModel } from '../../lib/DeviceModel.js';
2
+ export declare enum WasherState {
3
+ POWEROFF = "@WM_STATE_POWER_OFF_W",
4
+ INITIAL = "@WM_STATE_INITIAL_W",
5
+ PAUSE = "@WM_STATE_PAUSE_W",
6
+ RESERVED = "@WM_STATE_RESERVE_W",
7
+ DETECTING = "@WM_STATE_DETECTING_W",
8
+ RUNNING = "@WM_STATE_RUNNING_W",
9
+ RINSING = "@WM_STATE_RINSING_W",
10
+ SPINNING = "@WM_STATE_SPINNING_W",
11
+ DRYING = "@WM_STATE_DRYING_W",
12
+ END = "@WM_STATE_END_W",
13
+ COOLDOWN = "@WM_STATE_COOLDOWN_W",
14
+ RINSEHOLD = "@WM_STATE_RINSEHOLD_W",
15
+ WASH_REFRESHING = "@WM_STATE_WASH_REFRESHING_W",
16
+ STEAMSOFTENING = "@WM_STATE_STEAMSOFTENING_W",
17
+ ERROR = "@WM_STATE_ERROR_W"
18
+ }
19
+ export declare enum RemoteStart {
20
+ REMOTE_START_OFF = "@CP_OFF_EN_W",
21
+ REMOTE_START_ON = "@CP_ON_EN_W"
22
+ }
23
+ export declare enum ChildLock {
24
+ CHILDLOCK_OFF = "@CP_OFF_EN_W",
25
+ CHILDLOCK_ON = "@CP_ON_EN_W"
26
+ }
27
+ export declare enum SoilWash {
28
+ NO_SOILWASH = "-",
29
+ SOILWASH_TURBO_WASH = "@WM_FL24_TITAN_SOIL_LIGHT_W",
30
+ SOILWASH_TIMESAVE = "@WM_FL24_TITAN_SOIL_NORMAL_W",
31
+ SOILWASH_NORMAL = "@WM_FL24_TITAN_SOIL_HEAVY_W"
32
+ }
33
+ export default function WasherDryer(deviceModel: DeviceModel, decodedMonitor: any): {
34
+ washerDryer: {
35
+ state: string;
36
+ preState: string;
37
+ remoteStart: string;
38
+ initialBit: string;
39
+ childLock: string;
40
+ TCLCount: number;
41
+ reserveTimeHour: number;
42
+ reserveTimeMinute: number;
43
+ remainTimeHour: number;
44
+ remainTimeMinute: number;
45
+ initialTimeHour: number;
46
+ initialTimeMinute: number;
47
+ soilWash: string;
48
+ };
49
+ };
@@ -0,0 +1,56 @@
1
+ import { lookupEnumIndex, loopupEnum, safeParseInt } from '../helper.js';
2
+ export var WasherState;
3
+ (function (WasherState) {
4
+ WasherState["POWEROFF"] = "@WM_STATE_POWER_OFF_W";
5
+ WasherState["INITIAL"] = "@WM_STATE_INITIAL_W";
6
+ WasherState["PAUSE"] = "@WM_STATE_PAUSE_W";
7
+ WasherState["RESERVED"] = "@WM_STATE_RESERVE_W";
8
+ WasherState["DETECTING"] = "@WM_STATE_DETECTING_W";
9
+ WasherState["RUNNING"] = "@WM_STATE_RUNNING_W";
10
+ WasherState["RINSING"] = "@WM_STATE_RINSING_W";
11
+ WasherState["SPINNING"] = "@WM_STATE_SPINNING_W";
12
+ WasherState["DRYING"] = "@WM_STATE_DRYING_W";
13
+ WasherState["END"] = "@WM_STATE_END_W";
14
+ WasherState["COOLDOWN"] = "@WM_STATE_COOLDOWN_W";
15
+ WasherState["RINSEHOLD"] = "@WM_STATE_RINSEHOLD_W";
16
+ WasherState["WASH_REFRESHING"] = "@WM_STATE_WASH_REFRESHING_W";
17
+ WasherState["STEAMSOFTENING"] = "@WM_STATE_STEAMSOFTENING_W";
18
+ WasherState["ERROR"] = "@WM_STATE_ERROR_W";
19
+ })(WasherState || (WasherState = {}));
20
+ export var RemoteStart;
21
+ (function (RemoteStart) {
22
+ RemoteStart["REMOTE_START_OFF"] = "@CP_OFF_EN_W";
23
+ RemoteStart["REMOTE_START_ON"] = "@CP_ON_EN_W";
24
+ })(RemoteStart || (RemoteStart = {}));
25
+ export var ChildLock;
26
+ (function (ChildLock) {
27
+ ChildLock["CHILDLOCK_OFF"] = "@CP_OFF_EN_W";
28
+ ChildLock["CHILDLOCK_ON"] = "@CP_ON_EN_W";
29
+ })(ChildLock || (ChildLock = {}));
30
+ export var SoilWash;
31
+ (function (SoilWash) {
32
+ SoilWash["NO_SOILWASH"] = "-";
33
+ SoilWash["SOILWASH_TURBO_WASH"] = "@WM_FL24_TITAN_SOIL_LIGHT_W";
34
+ SoilWash["SOILWASH_TIMESAVE"] = "@WM_FL24_TITAN_SOIL_NORMAL_W";
35
+ SoilWash["SOILWASH_NORMAL"] = "@WM_FL24_TITAN_SOIL_HEAVY_W";
36
+ })(SoilWash || (SoilWash = {}));
37
+ export default function WasherDryer(deviceModel, decodedMonitor) {
38
+ return {
39
+ washerDryer: {
40
+ state: lookupEnumIndex(WasherState, loopupEnum(deviceModel, decodedMonitor, 'State')) || 'POWEROFF',
41
+ preState: lookupEnumIndex(WasherState, loopupEnum(deviceModel, decodedMonitor, 'PreState')) || 'POWEROFF',
42
+ remoteStart: lookupEnumIndex(RemoteStart, loopupEnum(deviceModel, decodedMonitor, 'RemoteStart')) || 'REMOTE_START_OFF',
43
+ initialBit: (decodedMonitor.InitialBit || false) ? 'INITIAL_BIT_ON' : 'INITIAL_BIT_OFF',
44
+ childLock: lookupEnumIndex(ChildLock, loopupEnum(deviceModel, decodedMonitor, 'ChildLock')) || 'CHILDLOCK_OFF',
45
+ TCLCount: (decodedMonitor.TCLCount || 0),
46
+ reserveTimeHour: safeParseInt(decodedMonitor.Reserve_Time_H),
47
+ reserveTimeMinute: safeParseInt(decodedMonitor.Reserve_Time_M),
48
+ remainTimeHour: safeParseInt(decodedMonitor.Remain_Time_H),
49
+ remainTimeMinute: safeParseInt(decodedMonitor.Remain_Time_M),
50
+ initialTimeHour: safeParseInt(decodedMonitor.Initial_Time_H),
51
+ initialTimeMinute: safeParseInt(decodedMonitor.Initial_Time_M),
52
+ soilWash: lookupEnumIndex(SoilWash, loopupEnum(deviceModel, decodedMonitor, 'Soil')) || 'NO_SOILWASH',
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=WasherDryer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WasherDryer.js","sourceRoot":"","sources":["../../../src/v1/transforms/WasherDryer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,CAAN,IAAY,WAgBX;AAhBD,WAAY,WAAW;IACrB,iDAAkC,CAAA;IAClC,8CAA+B,CAAA;IAC/B,0CAA2B,CAAA;IAC3B,+CAAgC,CAAA;IAChC,kDAAmC,CAAA;IACnC,8CAA+B,CAAA;IAC/B,8CAA+B,CAAA;IAC/B,gDAAiC,CAAA;IACjC,4CAA6B,CAAA;IAC7B,sCAAuB,CAAA;IACvB,gDAAiC,CAAA;IACjC,kDAAmC,CAAA;IACnC,8DAA+C,CAAA;IAC/C,4DAA6C,CAAA;IAC7C,0CAA2B,CAAA;AAC7B,CAAC,EAhBW,WAAW,KAAX,WAAW,QAgBtB;AAED,MAAM,CAAN,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,gDAAiC,CAAA;IACjC,8CAA+B,CAAA;AACjC,CAAC,EAHW,WAAW,KAAX,WAAW,QAGtB;AAED,MAAM,CAAN,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,2CAA8B,CAAA;IAC9B,yCAA4B,CAAA;AAC9B,CAAC,EAHW,SAAS,KAAT,SAAS,QAGpB;AAED,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,6BAAiB,CAAA;IACjB,+DAAmD,CAAA;IACnD,8DAAkD,CAAA;IAClD,2DAA+C,CAAA;AACjD,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,WAAwB,EAAE,cAAmB;IAC/E,OAAO;QACL,WAAW,EAAE;YACX,KAAK,EAAE,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,UAAU;YACnG,QAAQ,EAAE,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,IAAI,UAAU;YACzG,WAAW,EAAE,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC,IAAI,kBAAkB;YACvH,UAAU,EAAE,CAAC,cAAc,CAAC,UAAU,IAAI,KAAK,CAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB;YAClG,SAAS,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,IAAI,eAAe;YAC9G,QAAQ,EAAE,CAAC,cAAc,CAAC,QAAQ,IAAI,CAAC,CAAW;YAClD,eAAe,EAAE,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC;YAC5D,iBAAiB,EAAE,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC;YAC9D,cAAc,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;YAC1D,gBAAgB,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;YAC5D,eAAe,EAAE,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC;YAC5D,iBAAiB,EAAE,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC;YAC9D,QAAQ,EAAE,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI,aAAa;SACtG;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,40 @@
1
+ # Plugin Authorization Setting
2
+
3
+ ## Overview
4
+
5
+ This plugin requires LG account credentials to access your ThinQ devices.
6
+
7
+ ## Authorization Methods
8
+
9
+ ### Standard LG Account Access
10
+
11
+ The plugin requires an LG account with username/password to grant access.
12
+
13
+ ### For Third-Party Authenticated Accounts
14
+
15
+ If you use Google, Apple ID, or Facebook to sign into your LG account, you should create a secondary account using traditional credentials.
16
+
17
+ > **Note:** You can use the same email as your Google/Apple/Facebook account. LG treats them as separate accounts.
18
+
19
+ ### Refresh Token Alternative
20
+
21
+ Instead of providing credentials directly, you can generate a refresh token for enhanced privacy. This way you don't need to store your username/password in the plugin configuration.
22
+
23
+ Run the following commands:
24
+
25
+ ```bash
26
+ npm install -g homebridge-lg-thinq
27
+ thinq login [username] [password] -c US -l en-US
28
+ ```
29
+
30
+ Replace `[username]` and `[password]` with your LG account credentials. Adjust the country code (`-c`) and language (`-l`) as needed for your region.
31
+
32
+ This command will display a refresh token that you can enter in the plugin configuration instead of your username/password.
33
+
34
+ ## Summary
35
+
36
+ The plugin offers three authentication pathways:
37
+
38
+ 1. **Direct credentials**: Enter username/password directly in the plugin settings
39
+ 2. **Secondary account**: Create a new LG account for third-party authenticated users
40
+ 3. **Refresh token**: Generate a token via CLI for enhanced privacy
@@ -0,0 +1,68 @@
1
+ # Device Configuration
2
+
3
+ This document covers configuration options for specific device types in the homebridge-lg-thinq plugin.
4
+
5
+ ## Washer / WashTower / Dryer
6
+
7
+ Configuration includes a required device ID and optional settings:
8
+
9
+ | Option | Default | Description |
10
+ |--------|---------|-------------|
11
+ | `washer_trigger` | `false` | Enable program finished trigger. Works as an Occupancy sensor. |
12
+ | `washer_door_lock` | `false` | Enable door lock status monitoring. |
13
+
14
+ ## Air Conditioner
15
+
16
+ | Option | Description |
17
+ |--------|-------------|
18
+ | `ac_mode` | Set supported modes: `cooling`, `heating`, or `both` |
19
+ | `ac_swing_mode` | Set swing direction: `vertical`, `horizontal`, or `both` |
20
+ | `ac_air_quality` | Enable air quality sensor (if supported by device) |
21
+ | `ac_temperature_sensor` | Expose temperature as a separate sensor for automations |
22
+ | `ac_buttons` | Custom button array for preset mode configurations |
23
+
24
+ > **Note:** The swing mode feature will turn on/off swing mode only. It cannot control a specified swing direction.
25
+
26
+ ## Refrigerator
27
+
28
+ Optional features that can be controlled via switches:
29
+
30
+ | Option | Description |
31
+ |--------|-------------|
32
+ | `ref_express_freezer` | Ice Plus functionality |
33
+ | `ref_express_fridge` | Express Fridge mode |
34
+ | `ref_eco_friendly` | Energy-saving operation |
35
+
36
+ ## Example Configuration
37
+
38
+ ```json
39
+ {
40
+ "platform": "LGThinQ",
41
+ "name": "LG ThinQ",
42
+ "auth_mode": "token",
43
+ "refresh_token": "your-refresh-token",
44
+ "devices": [
45
+ {
46
+ "id": "your-device-id",
47
+ "name": "My Washer",
48
+ "washer_trigger": true,
49
+ "washer_door_lock": true
50
+ },
51
+ {
52
+ "id": "your-ac-device-id",
53
+ "name": "Living Room AC",
54
+ "ac_mode": "both",
55
+ "ac_swing_mode": "vertical",
56
+ "ac_air_quality": true
57
+ },
58
+ {
59
+ "id": "your-fridge-device-id",
60
+ "name": "Kitchen Fridge",
61
+ "ref_express_freezer": true,
62
+ "ref_eco_friendly": true
63
+ }
64
+ ]
65
+ }
66
+ ```
67
+
68
+ All configurations require a device ID. Display names are optional.
@@ -0,0 +1,120 @@
1
+ <link rel="stylesheet" href="styles.css">
2
+
3
+ <div class="lg-header">
4
+ <h2>LG ThinQ</h2>
5
+ <p class="text-muted">Homebridge plugin to integrate LG ThinQ devices into HomeKit</p>
6
+ </div>
7
+
8
+ <!-- Step 1: Login -->
9
+ <div id="step-login" class="step-container">
10
+ <div class="step-header">
11
+ <div class="step-number">1</div>
12
+ <h3 class="step-title">Connect Your LG Account</h3>
13
+ </div>
14
+
15
+ <!-- Active session notice -->
16
+ <div id="active-session-notice" class="alert alert-info hidden">
17
+ <div class="d-flex justify-content-between align-items-center">
18
+ <div>
19
+ <strong>Active Session Detected</strong>
20
+ <p class="mb-0 small">Using the existing session from Homebridge</p>
21
+ </div>
22
+ <button id="btn-new-login" class="btn btn-sm btn-outline-primary">Login with Different Account</button>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="card" id="login-form">
27
+ <div class="card-body">
28
+ <div class="mb-3">
29
+ <label for="country_language" class="form-label">Country / Language</label>
30
+ <select class="form-select" id="country_language"></select>
31
+ <div class="form-text">Select your LG account region</div>
32
+ </div>
33
+
34
+ <div class="mb-3">
35
+ <label for="username" class="form-label">Email</label>
36
+ <input type="text" class="form-control" id="username" placeholder="your@email.com">
37
+ <div class="form-text">Enter your LG ThinQ account email</div>
38
+ </div>
39
+
40
+ <div class="mb-3">
41
+ <label for="password" class="form-label">Password</label>
42
+ <input type="password" class="form-control" id="password" placeholder="••••••••">
43
+ </div>
44
+
45
+ <div class="form-check mb-3">
46
+ <input class="form-check-input" type="checkbox" id="rememberCredentials">
47
+ <label class="form-check-label" for="rememberCredentials">Remember username & password (optional)</label>
48
+ </div>
49
+
50
+ <button id="btn-login" class="btn btn-primary">
51
+ <span class="spinner-border spinner-border-sm hidden" id="login-spinner"></span>
52
+ Connect Account
53
+ </button>
54
+
55
+ <div class="wiki-link">
56
+ <p class="small text-muted mb-2">Using OAuth login (Facebook, Amazon, etc.)?</p>
57
+ <a href="https://github.com/mp-consulting/homebridge-lg-thinq/wiki/Plugin-Authorization-Setting" target="_blank">
58
+ View Plugin Authorization Wiki
59
+ </a>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ <!-- Step 2: Devices -->
66
+ <div id="step-devices" class="step-container hidden">
67
+ <div class="step-header">
68
+ <div class="step-number">2</div>
69
+ <h3 class="step-title">Your Devices</h3>
70
+ </div>
71
+
72
+ <div class="alert alert-success mb-3" id="success-alert">
73
+ <strong>Success!</strong> Your LG account is connected. Found <span id="device-count">0</span> devices.
74
+ </div>
75
+
76
+ <div class="card mb-3">
77
+ <div class="card-header d-flex justify-content-between align-items-center">
78
+ <span>Discovered Devices</span>
79
+ <button id="btn-refresh" class="btn btn-sm btn-outline-secondary">
80
+ <span class="spinner-border spinner-border-sm hidden" id="refresh-spinner"></span>
81
+ Refresh
82
+ </button>
83
+ </div>
84
+ <div class="card-body device-list" id="device-list">
85
+ <!-- Devices will be populated here -->
86
+ </div>
87
+ </div>
88
+
89
+ <div class="card mb-3">
90
+ <div class="card-header">Plugin Settings</div>
91
+ <div class="card-body">
92
+ <div class="form-check mb-2">
93
+ <input class="form-check-input" type="checkbox" id="thinq1">
94
+ <label class="form-check-label" for="thinq1">Enable ThinQ1 support (older devices)</label>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <div class="d-flex gap-2">
100
+ <button id="btn-save" class="btn btn-success">Save Configuration</button>
101
+ <button id="btn-schema" class="btn btn-outline-primary">Advanced Settings</button>
102
+ </div>
103
+ </div>
104
+
105
+ <!-- Step 3: Complete -->
106
+ <div id="step-complete" class="step-container hidden">
107
+ <div class="step-header">
108
+ <div class="step-number" style="background-color: var(--bs-success);">✓</div>
109
+ <h3 class="step-title">Configuration Complete</h3>
110
+ </div>
111
+
112
+ <div class="alert alert-success">
113
+ <strong>All done!</strong> Your LG ThinQ plugin is configured. Please restart Homebridge to apply the changes.
114
+ </div>
115
+
116
+ <button id="btn-restart" class="btn btn-warning">Restart Homebridge</button>
117
+ </div>
118
+
119
+ <script src="js/countries.js"></script>
120
+ <script src="js/app.js"></script>