@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.
- package/.claude/settings.local.json +15 -0
- package/CHANGELOG.md +98 -0
- package/LICENSE +176 -0
- package/README.md +114 -0
- package/config.schema.json +399 -0
- package/dist/__tests__/baseDevice.spec.d.ts +1 -0
- package/dist/__tests__/baseDevice.spec.js +96 -0
- package/dist/__tests__/baseDevice.spec.js.map +1 -0
- package/dist/__tests__/deviceControl.coercion.spec.d.ts +1 -0
- package/dist/__tests__/deviceControl.coercion.spec.js +53 -0
- package/dist/__tests__/deviceControl.coercion.spec.js.map +1 -0
- package/dist/__tests__/helper.spec.d.ts +1 -0
- package/dist/__tests__/helper.spec.js +74 -0
- package/dist/__tests__/helper.spec.js.map +1 -0
- package/dist/baseDevice.d.ts +40 -0
- package/dist/baseDevice.js +85 -0
- package/dist/baseDevice.js.map +1 -0
- package/dist/baseDevice.spec.d.ts +1 -0
- package/dist/baseDevice.spec.js +107 -0
- package/dist/baseDevice.spec.js.map +1 -0
- package/dist/characteristics/TotalConsumption.d.ts +2 -0
- package/dist/characteristics/TotalConsumption.js +17 -0
- package/dist/characteristics/TotalConsumption.js.map +1 -0
- package/dist/characteristics/index.d.ts +2 -0
- package/dist/characteristics/index.js +7 -0
- package/dist/characteristics/index.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +89 -0
- package/dist/cli.js.map +1 -0
- package/dist/devices/AeroTower.d.ts +24 -0
- package/dist/devices/AeroTower.js +113 -0
- package/dist/devices/AeroTower.js.map +1 -0
- package/dist/devices/AirConditioner.d.ts +425 -0
- package/dist/devices/AirConditioner.js +1253 -0
- package/dist/devices/AirConditioner.js.map +1 -0
- package/dist/devices/AirPurifier.d.ts +50 -0
- package/dist/devices/AirPurifier.js +281 -0
- package/dist/devices/AirPurifier.js.map +1 -0
- package/dist/devices/Dehumidifier.d.ts +28 -0
- package/dist/devices/Dehumidifier.js +175 -0
- package/dist/devices/Dehumidifier.js.map +1 -0
- package/dist/devices/Dishwasher.d.ts +64 -0
- package/dist/devices/Dishwasher.js +740 -0
- package/dist/devices/Dishwasher.js.map +1 -0
- package/dist/devices/Microwave.d.ts +128 -0
- package/dist/devices/Microwave.js +1939 -0
- package/dist/devices/Microwave.js.map +1 -0
- package/dist/devices/Oven.d.ts +148 -0
- package/dist/devices/Oven.js +1850 -0
- package/dist/devices/Oven.js.map +1 -0
- package/dist/devices/RangeHood.d.ts +16 -0
- package/dist/devices/RangeHood.js +99 -0
- package/dist/devices/RangeHood.js.map +1 -0
- package/dist/devices/Refrigerator.d.ts +50 -0
- package/dist/devices/Refrigerator.js +325 -0
- package/dist/devices/Refrigerator.js.map +1 -0
- package/dist/devices/Styler.d.ts +27 -0
- package/dist/devices/Styler.js +76 -0
- package/dist/devices/Styler.js.map +1 -0
- package/dist/devices/WasherDryer.d.ts +39 -0
- package/dist/devices/WasherDryer.js +170 -0
- package/dist/devices/WasherDryer.js.map +1 -0
- package/dist/devices/WasherDryer2.d.ts +9 -0
- package/dist/devices/WasherDryer2.js +16 -0
- package/dist/devices/WasherDryer2.js.map +1 -0
- package/dist/errors/AuthenticationError.d.ts +2 -0
- package/dist/errors/AuthenticationError.js +3 -0
- package/dist/errors/AuthenticationError.js.map +1 -0
- package/dist/errors/ManualProcessNeeded.d.ts +3 -0
- package/dist/errors/ManualProcessNeeded.js +4 -0
- package/dist/errors/ManualProcessNeeded.js.map +1 -0
- package/dist/errors/MonitorError.d.ts +2 -0
- package/dist/errors/MonitorError.js +3 -0
- package/dist/errors/MonitorError.js.map +1 -0
- package/dist/errors/NotConnectedError.d.ts +3 -0
- package/dist/errors/NotConnectedError.js +4 -0
- package/dist/errors/NotConnectedError.js.map +1 -0
- package/dist/errors/TokenError.d.ts +2 -0
- package/dist/errors/TokenError.js +3 -0
- package/dist/errors/TokenError.js.map +1 -0
- package/dist/errors/TokenExpiredError.d.ts +3 -0
- package/dist/errors/TokenExpiredError.js +4 -0
- package/dist/errors/TokenExpiredError.js.map +1 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/helper.d.ts +24 -0
- package/dist/helper.js +66 -0
- package/dist/helper.js.map +1 -0
- package/dist/helper.spec.d.ts +1 -0
- package/dist/helper.spec.js +74 -0
- package/dist/helper.spec.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/API.d.ts +141 -0
- package/dist/lib/API.js +362 -0
- package/dist/lib/API.js.map +1 -0
- package/dist/lib/API.spec.d.ts +1 -0
- package/dist/lib/API.spec.js +55 -0
- package/dist/lib/API.spec.js.map +1 -0
- package/dist/lib/Auth.d.ts +99 -0
- package/dist/lib/Auth.js +348 -0
- package/dist/lib/Auth.js.map +1 -0
- package/dist/lib/Auth.spec.d.ts +1 -0
- package/dist/lib/Auth.spec.js +111 -0
- package/dist/lib/Auth.spec.js.map +1 -0
- package/dist/lib/Device.d.ts +88 -0
- package/dist/lib/Device.js +95 -0
- package/dist/lib/Device.js.map +1 -0
- package/dist/lib/Device.spec.d.ts +1 -0
- package/dist/lib/Device.spec.js +53 -0
- package/dist/lib/Device.spec.js.map +1 -0
- package/dist/lib/DeviceModel.d.ts +164 -0
- package/dist/lib/DeviceModel.js +321 -0
- package/dist/lib/DeviceModel.js.map +1 -0
- package/dist/lib/DeviceModel.spec.d.ts +1 -0
- package/dist/lib/DeviceModel.spec.js +90 -0
- package/dist/lib/DeviceModel.spec.js.map +1 -0
- package/dist/lib/Gateway.d.ts +18 -0
- package/dist/lib/Gateway.js +25 -0
- package/dist/lib/Gateway.js.map +1 -0
- package/dist/lib/Gateway.spec.d.ts +1 -0
- package/dist/lib/Gateway.spec.js +35 -0
- package/dist/lib/Gateway.spec.js.map +1 -0
- package/dist/lib/Persist.d.ts +101 -0
- package/dist/lib/Persist.js +245 -0
- package/dist/lib/Persist.js.map +1 -0
- package/dist/lib/Persist.spec.d.ts +1 -0
- package/dist/lib/Persist.spec.js +90 -0
- package/dist/lib/Persist.spec.js.map +1 -0
- package/dist/lib/Session.d.ts +80 -0
- package/dist/lib/Session.js +100 -0
- package/dist/lib/Session.js.map +1 -0
- package/dist/lib/Session.spec.d.ts +1 -0
- package/dist/lib/Session.spec.js +43 -0
- package/dist/lib/Session.spec.js.map +1 -0
- package/dist/lib/ThinQ.d.ts +28 -0
- package/dist/lib/ThinQ.js +373 -0
- package/dist/lib/ThinQ.js.map +1 -0
- package/dist/lib/__tests__/API.spec.d.ts +1 -0
- package/dist/lib/__tests__/API.spec.js +55 -0
- package/dist/lib/__tests__/API.spec.js.map +1 -0
- package/dist/lib/__tests__/Auth.spec.d.ts +1 -0
- package/dist/lib/__tests__/Auth.spec.js +110 -0
- package/dist/lib/__tests__/Auth.spec.js.map +1 -0
- package/dist/lib/__tests__/Device.spec.d.ts +1 -0
- package/dist/lib/__tests__/Device.spec.js +53 -0
- package/dist/lib/__tests__/Device.spec.js.map +1 -0
- package/dist/lib/__tests__/DeviceModel.spec.d.ts +1 -0
- package/dist/lib/__tests__/DeviceModel.spec.js +90 -0
- package/dist/lib/__tests__/DeviceModel.spec.js.map +1 -0
- package/dist/lib/__tests__/Gateway.spec.d.ts +1 -0
- package/dist/lib/__tests__/Gateway.spec.js +35 -0
- package/dist/lib/__tests__/Gateway.spec.js.map +1 -0
- package/dist/lib/__tests__/Persist.spec.d.ts +1 -0
- package/dist/lib/__tests__/Persist.spec.js +90 -0
- package/dist/lib/__tests__/Persist.spec.js.map +1 -0
- package/dist/lib/__tests__/Session.spec.d.ts +1 -0
- package/dist/lib/__tests__/Session.spec.js +43 -0
- package/dist/lib/__tests__/Session.spec.js.map +1 -0
- package/dist/lib/constants.d.ts +95 -0
- package/dist/lib/constants.js +106 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/request.d.ts +2 -0
- package/dist/lib/request.js +66 -0
- package/dist/lib/request.js.map +1 -0
- package/dist/platform.d.ts +41 -0
- package/dist/platform.js +229 -0
- package/dist/platform.js.map +1 -0
- package/dist/settings.d.ts +8 -0
- package/dist/settings.js +9 -0
- package/dist/settings.js.map +1 -0
- package/dist/status/BaseStatus.d.ts +48 -0
- package/dist/status/BaseStatus.js +59 -0
- package/dist/status/BaseStatus.js.map +1 -0
- package/dist/types/snapshots.d.ts +142 -0
- package/dist/types/snapshots.js +6 -0
- package/dist/types/snapshots.js.map +1 -0
- package/dist/utils/__tests__/normalize.spec.d.ts +1 -0
- package/dist/utils/__tests__/normalize.spec.js +95 -0
- package/dist/utils/__tests__/normalize.spec.js.map +1 -0
- package/dist/utils/normalize.d.ts +22 -0
- package/dist/utils/normalize.js +51 -0
- package/dist/utils/normalize.js.map +1 -0
- package/dist/v1/__tests__/prepareControlData.spec.d.ts +1 -0
- package/dist/v1/__tests__/prepareControlData.spec.js +48 -0
- package/dist/v1/__tests__/prepareControlData.spec.js.map +1 -0
- package/dist/v1/devices/AC.d.ts +13 -0
- package/dist/v1/devices/AC.js +112 -0
- package/dist/v1/devices/AC.js.map +1 -0
- package/dist/v1/devices/AirPurifier.d.ts +15 -0
- package/dist/v1/devices/AirPurifier.js +57 -0
- package/dist/v1/devices/AirPurifier.js.map +1 -0
- package/dist/v1/devices/RangeHood.d.ts +6 -0
- package/dist/v1/devices/RangeHood.js +12 -0
- package/dist/v1/devices/RangeHood.js.map +1 -0
- package/dist/v1/devices/Refrigerator.d.ts +17 -0
- package/dist/v1/devices/Refrigerator.js +69 -0
- package/dist/v1/devices/Refrigerator.js.map +1 -0
- package/dist/v1/devices/Washer.d.ts +10 -0
- package/dist/v1/devices/Washer.js +23 -0
- package/dist/v1/devices/Washer.js.map +1 -0
- package/dist/v1/devices/index.d.ts +6 -0
- package/dist/v1/devices/index.js +7 -0
- package/dist/v1/devices/index.js.map +1 -0
- package/dist/v1/helper.d.ts +14 -0
- package/dist/v1/helper.js +111 -0
- package/dist/v1/helper.js.map +1 -0
- package/dist/v1/transforms/AirPurifierState.d.ts +2 -0
- package/dist/v1/transforms/AirPurifierState.js +9 -0
- package/dist/v1/transforms/AirPurifierState.js.map +1 -0
- package/dist/v1/transforms/AirState.d.ts +9 -0
- package/dist/v1/transforms/AirState.js +55 -0
- package/dist/v1/transforms/AirState.js.map +1 -0
- package/dist/v1/transforms/HoodState.d.ts +17 -0
- package/dist/v1/transforms/HoodState.js +20 -0
- package/dist/v1/transforms/HoodState.js.map +1 -0
- package/dist/v1/transforms/RefState.d.ts +6 -0
- package/dist/v1/transforms/RefState.js +29 -0
- package/dist/v1/transforms/RefState.js.map +1 -0
- package/dist/v1/transforms/WasherDryer.d.ts +49 -0
- package/dist/v1/transforms/WasherDryer.js +56 -0
- package/dist/v1/transforms/WasherDryer.js.map +1 -0
- package/docs/authorization.md +40 -0
- package/docs/device-configuration.md +68 -0
- package/homebridge-ui/public/index.html +120 -0
- package/homebridge-ui/public/js/app.js +300 -0
- package/homebridge-ui/public/js/countries.js +233 -0
- package/homebridge-ui/public/styles.css +185 -0
- package/homebridge-ui/server.js +103 -0
- package/jest.config.ts +39 -0
- package/package.json +83 -0
- package/sample/README.md +10 -0
- package/sample/airconditioner-model.json +3080 -0
- package/sample/airconditioner-snapshot.json +49 -0
- package/sample/airconditioner.json +157 -0
- package/sample/dishwasher-model.json +869 -0
- package/sample/dishwasher.json +125 -0
- package/sample/washer_dryer-model.json +1294 -0
- 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,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,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>
|