@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,40 @@
1
+ import { LGThinQHomebridgePlatform } from './platform.js';
2
+ import { Logger, PlatformAccessory, Service, WithUUID } from 'homebridge';
3
+ import { Device } from './lib/Device.js';
4
+ import { EventEmitter } from 'events';
5
+ type ServiceConstructor = WithUUID<typeof Service>;
6
+ export interface DeviceControlPayload {
7
+ dataKey: string | null;
8
+ dataValue: unknown;
9
+ dataSetList?: Record<string, unknown> | null;
10
+ dataGetList?: Record<string, unknown> | null;
11
+ }
12
+ export type AccessoryContext = {
13
+ device: Device;
14
+ };
15
+ export declare class BaseDevice extends EventEmitter {
16
+ readonly platform: LGThinQHomebridgePlatform;
17
+ readonly accessory: PlatformAccessory<AccessoryContext>;
18
+ protected readonly logger: Logger;
19
+ constructor(platform: LGThinQHomebridgePlatform, accessory: PlatformAccessory<AccessoryContext>, logger: Logger);
20
+ updateAccessoryCharacteristic(device: Device): void;
21
+ update(snapshot: any): void;
22
+ get config(): Record<string, any>;
23
+ /**
24
+ * Helper method to safely control a device with error handling.
25
+ * Wraps ThinQ deviceControl with try/catch and returns success/failure.
26
+ */
27
+ protected controlDevice(payload: DeviceControlPayload, onSuccess?: () => void): Promise<boolean>;
28
+ /**
29
+ * Get or create a service with the given type and name.
30
+ * Automatically adds ConfiguredName characteristic.
31
+ */
32
+ protected getOrCreateService(serviceType: ServiceConstructor, name: string, subType?: string): Service;
33
+ /**
34
+ * Conditionally create or remove a service based on a boolean flag.
35
+ * Returns the service if enabled, undefined if disabled.
36
+ */
37
+ protected ensureService(serviceType: ServiceConstructor, name: string, enabled: boolean, subType?: string): Service | undefined;
38
+ static model(): string;
39
+ }
40
+ export {};
@@ -0,0 +1,85 @@
1
+ import { EventEmitter } from 'events';
2
+ export class BaseDevice extends EventEmitter {
3
+ platform;
4
+ accessory;
5
+ logger;
6
+ constructor(platform, accessory, logger) {
7
+ super();
8
+ this.platform = platform;
9
+ this.accessory = accessory;
10
+ this.logger = logger;
11
+ const device = accessory.context.device;
12
+ const { AccessoryInformation } = this.platform.Service;
13
+ const serviceAccessoryInformation = accessory.getService(AccessoryInformation) || accessory.addService(AccessoryInformation);
14
+ // set accessory information
15
+ serviceAccessoryInformation
16
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'LG')
17
+ .setCharacteristic(this.platform.Characteristic.Model, device.salesModel || device.model || 'Unknown')
18
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, this.config.serial_number || device.serialNumber || 'Unknown');
19
+ }
20
+ updateAccessoryCharacteristic(device) {
21
+ this.accessory.context.device = device;
22
+ }
23
+ update(snapshot) {
24
+ this.platform.log.debug('[' + this.accessory.context.device.name + '] Received snapshot: ', JSON.stringify(snapshot));
25
+ this.accessory.context.device.data.snapshot = { ...this.accessory.context.device.snapshot, ...snapshot };
26
+ this.updateAccessoryCharacteristic(this.accessory.context.device);
27
+ }
28
+ get config() {
29
+ return this.platform.config.devices.find((enabled) => enabled.id === this.accessory.context.device.id) || {};
30
+ }
31
+ /**
32
+ * Helper method to safely control a device with error handling.
33
+ * Wraps ThinQ deviceControl with try/catch and returns success/failure.
34
+ */
35
+ async controlDevice(payload, onSuccess) {
36
+ const device = this.accessory.context.device;
37
+ try {
38
+ const result = await this.platform.ThinQ?.deviceControl(device.id, payload);
39
+ if (result && onSuccess) {
40
+ onSuccess();
41
+ }
42
+ return !!result;
43
+ }
44
+ catch (error) {
45
+ this.logger.error(`[${device.name}] Device control failed:`, error);
46
+ throw new this.platform.api.hap.HapStatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
47
+ }
48
+ }
49
+ /**
50
+ * Get or create a service with the given type and name.
51
+ * Automatically adds ConfiguredName characteristic.
52
+ */
53
+ getOrCreateService(serviceType, name, subType) {
54
+ const effectiveSubType = subType || name;
55
+ const service = this.accessory.getService(effectiveSubType)
56
+ || this.accessory.addService(serviceType, name, effectiveSubType);
57
+ // Add ConfiguredName for better HomeKit display
58
+ service.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName);
59
+ service.updateCharacteristic(this.platform.Characteristic.ConfiguredName, name);
60
+ return service;
61
+ }
62
+ /**
63
+ * Conditionally create or remove a service based on a boolean flag.
64
+ * Returns the service if enabled, undefined if disabled.
65
+ */
66
+ ensureService(serviceType, name, enabled, subType) {
67
+ const existingService = subType
68
+ ? this.accessory.getService(subType)
69
+ : this.accessory.getService(serviceType);
70
+ if (enabled) {
71
+ if (!existingService) {
72
+ return this.getOrCreateService(serviceType, name, subType);
73
+ }
74
+ return existingService;
75
+ }
76
+ else if (existingService) {
77
+ this.accessory.removeService(existingService);
78
+ }
79
+ return undefined;
80
+ }
81
+ static model() {
82
+ return '';
83
+ }
84
+ }
85
+ //# sourceMappingURL=baseDevice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseDevice.js","sourceRoot":"","sources":["../src/baseDevice.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,107 @@
1
+ import { BaseDevice } from './baseDevice.js';
2
+ import { Device } from './lib/Device.js';
3
+ import { describe, expect, it, jest, beforeEach } from '@jest/globals';
4
+ // Mock dependencies
5
+ jest.mock('./platform.js');
6
+ jest.mock('./lib/Device');
7
+ // Test suite for BaseDevice class
8
+ describe('BaseDevice', () => {
9
+ let platform;
10
+ let accessory;
11
+ let logger;
12
+ let device;
13
+ let baseDevice;
14
+ const mockDeviceData = {
15
+ deviceId: '12345',
16
+ alias: 'Smart Fridge',
17
+ deviceType: 101,
18
+ modelName: 'FR123-US',
19
+ modelJsonUri: 'https://example.com/model.json',
20
+ manufacture: {
21
+ macAddress: '00:1A:2B:3C:4D:5E',
22
+ salesModel: 'FR123',
23
+ serialNo: 'SN123456789',
24
+ manufactureModel: 'FR123-M',
25
+ },
26
+ online: true,
27
+ modemInfo: {
28
+ appVersion: '1.0.0',
29
+ modelName: 'FR123-MODEM',
30
+ },
31
+ snapshot: {
32
+ online: true,
33
+ },
34
+ platformType: 'ThinQ2',
35
+ };
36
+ beforeEach(() => {
37
+ logger = {
38
+ debug: jest.fn(),
39
+ info: jest.fn(),
40
+ warn: jest.fn(),
41
+ error: jest.fn(),
42
+ };
43
+ platform = {
44
+ Service: {
45
+ AccessoryInformation: function AccessoryInformation() { },
46
+ },
47
+ Characteristic: {
48
+ Manufacturer: 'Manufacturer',
49
+ Model: 'Model',
50
+ SerialNumber: 'SerialNumber',
51
+ },
52
+ config: {
53
+ devices: [
54
+ { id: '12345', customConfig: true },
55
+ ],
56
+ },
57
+ log: logger,
58
+ };
59
+ accessory = {
60
+ context: {
61
+ device: new Device(mockDeviceData),
62
+ },
63
+ getService: jest.fn().mockReturnValue(null),
64
+ addService: jest.fn().mockImplementation(() => ({
65
+ setCharacteristic: jest.fn().mockReturnThis(),
66
+ })),
67
+ };
68
+ device = accessory.context.device;
69
+ });
70
+ it('should set accessory information on initialization', () => {
71
+ baseDevice = new BaseDevice(platform, accessory, logger);
72
+ expect(accessory.addService).toHaveBeenCalled();
73
+ const calledArg = accessory.addService.mock.calls[0][0];
74
+ if (typeof calledArg === 'function') {
75
+ expect(calledArg.name).toBe('AccessoryInformation');
76
+ }
77
+ else {
78
+ expect(calledArg.displayName).toBe('AccessoryInformation');
79
+ }
80
+ });
81
+ it('should update accessory characteristics', () => {
82
+ baseDevice = new BaseDevice(platform, accessory, logger);
83
+ const newDevice = { ...device, name: 'Updated Device' };
84
+ baseDevice.updateAccessoryCharacteristic(newDevice);
85
+ expect(accessory.context.device).toEqual(newDevice);
86
+ });
87
+ // it('should update device snapshot and accessory characteristics', () => {
88
+ // baseDevice = new BaseDevice(platform, accessory, logger);
89
+ // const snapshot = { key: 'value' };
90
+ // baseDevice.update(snapshot);
91
+ // expect(device.data.snapshot).toEqual({ key: 'value' });
92
+ // expect(accessory.context.device).toEqual(device);
93
+ // });
94
+ // it('should return the correct configuration for the device', () => {
95
+ // baseDevice = new BaseDevice(platform, accessory, logger);
96
+ // expect(baseDevice.config).toEqual({ id: '12345', customConfig: true });
97
+ // });
98
+ it('should return an empty object if no configuration is found for the device', () => {
99
+ baseDevice = new BaseDevice(platform, accessory, logger);
100
+ platform.config.devices = [];
101
+ expect(baseDevice.config).toEqual({});
102
+ });
103
+ it('should return an empty string for the static model method', () => {
104
+ expect(BaseDevice.model()).toBe('');
105
+ });
106
+ });
107
+ //# sourceMappingURL=baseDevice.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseDevice.spec.js","sourceRoot":"","sources":["../src/baseDevice.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { WithUUID, Characteristic } from 'homebridge';
2
+ export default function TotalConsumption(DefaultCharacteristic: typeof Characteristic): WithUUID<new () => Characteristic>;
@@ -0,0 +1,17 @@
1
+ export default function TotalConsumption(DefaultCharacteristic) {
2
+ return class TotalConsumption extends DefaultCharacteristic {
3
+ // Eve Energy - Total consumption
4
+ static UUID = 'E863F10C-079E-48FF-8F27-9C2605A29F52';
5
+ constructor() {
6
+ super('Total Consumption', TotalConsumption.UUID, {
7
+ format: "float" /* Formats.FLOAT */,
8
+ unit: 'kWh',
9
+ minValue: 0,
10
+ maxValue: 1000000,
11
+ minStep: 0.01,
12
+ perms: ["pr" /* Perms.PAIRED_READ */, "ev" /* Perms.NOTIFY */],
13
+ });
14
+ }
15
+ };
16
+ }
17
+ //# sourceMappingURL=TotalConsumption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TotalConsumption.js","sourceRoot":"","sources":["../../src/characteristics/TotalConsumption.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,qBAA4C;IAE5C,OAAO,MAAM,gBAAiB,SAAQ,qBAAqB;QACzD,iCAAiC;QACjC,MAAM,CAAU,IAAI,GAAG,sCAAsC,CAAC;QAE9D;YACE,KAAK,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,IAAI,EAAE;gBAChD,MAAM,6BAAe;gBACrB,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,CAAC;gBACX,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,uDAAiC;aACzC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Characteristic as CharacteristicType, WithUUID } from 'homebridge';
2
+ export default function characteristic(Characteristic: typeof CharacteristicType): Record<'TotalConsumption', WithUUID<new () => CharacteristicType>>;
@@ -0,0 +1,7 @@
1
+ import TotalConsumption from './TotalConsumption.js';
2
+ export default function characteristic(Characteristic) {
3
+ return {
4
+ TotalConsumption: TotalConsumption(Characteristic),
5
+ };
6
+ }
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/characteristics/index.ts"],"names":[],"mappings":"AAKA,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AAErD,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,cAAyC;IAMzC,OAAO;QACL,gBAAgB,EAAE,gBAAgB,CAAC,cAAc,CAAC;KACnD,CAAC;AACJ,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { API } from './lib/API.js';
4
+ import { Auth } from './lib/Auth.js';
5
+ import { URL } from 'url';
6
+ import * as readline from 'readline';
7
+ const makeLogger = () => console;
8
+ const input = (question) => new Promise((resolve) => {
9
+ const rl = readline.createInterface(process.stdin, process.stdout);
10
+ rl.question(question, (answer) => resolve(answer));
11
+ });
12
+ const program = new Command();
13
+ const options = {
14
+ country: 'US',
15
+ language: 'en-US',
16
+ };
17
+ program
18
+ .option('-c, --country <type>', 'Country code for account', options.country)
19
+ .on('option:country', (value) => options.country = value)
20
+ .option('-l, --language <type>', 'Language code for account', options.language)
21
+ .on('option:language', (value) => options.language = value);
22
+ program
23
+ .command('login')
24
+ .description('Obtain refresh_token from LG account')
25
+ .argument('<username>', 'LG username')
26
+ .argument('<password>', 'LG password')
27
+ .action(async (username, password) => {
28
+ console.info('Start login: username =', username, ', password =', password, ', country =', options.country, ', language =', options.language);
29
+ const logger = makeLogger();
30
+ try {
31
+ const api = new API(options.country, options.language, logger);
32
+ const gateway = await api.gateway();
33
+ const auth = new Auth(gateway, logger);
34
+ const session = await auth.login(username, password);
35
+ console.info('Your refresh_token:', session.refreshToken);
36
+ }
37
+ catch (err) {
38
+ console.error(err);
39
+ }
40
+ process.exit(0);
41
+ });
42
+ program
43
+ .command('auth')
44
+ .description('Obtain refresh_token from account logged by Google Account, Apple ID')
45
+ .action(async () => {
46
+ const logger = makeLogger();
47
+ const api = new API(options.country, options.language, logger);
48
+ const gateway = await api.gateway();
49
+ const auth = new Auth(gateway, logger);
50
+ const loginUrl = new URL(await auth.getLoginUrl());
51
+ const origin = loginUrl.origin;
52
+ loginUrl.host = 'us.m.lgaccount.com';
53
+ loginUrl.searchParams.set('division', 'ha'); // enable Apple ID
54
+ loginUrl.searchParams.set('redirect_uri', origin + '/login/iabClose');
55
+ loginUrl.searchParams.set('callback_url', origin + '/login/iabClose');
56
+ console.info('Log in here:', loginUrl.href);
57
+ const callbackUrl = await input('Then paste the URL where the browser is redirected: ');
58
+ const url = new URL(callbackUrl);
59
+ const refresh_token = url.searchParams.get('refresh_token');
60
+ if (refresh_token) {
61
+ console.info('Your refresh_token:', refresh_token);
62
+ process.exit(0);
63
+ return;
64
+ }
65
+ const username = url.searchParams.get('user_id'), thirdparty_token = url.searchParams.get('user_thirdparty_token'), id_type = url.searchParams.get('user_id_type') || '';
66
+ const thirdparty = {
67
+ APPL: 'apple',
68
+ FBK: 'facebook',
69
+ GGL: 'google',
70
+ AMZ: 'amazon',
71
+ };
72
+ if (!username || !thirdparty_token || typeof thirdparty[id_type] === 'undefined') {
73
+ console.error('redirected url not valid, please try again or use LG account method');
74
+ process.exit(0);
75
+ return;
76
+ }
77
+ try {
78
+ const session = await auth.loginStep2(username, thirdparty_token, {
79
+ third_party: thirdparty[id_type],
80
+ });
81
+ console.info('Your refresh_token:', session.refreshToken);
82
+ }
83
+ catch (err) {
84
+ console.error(err);
85
+ }
86
+ process.exit(0);
87
+ });
88
+ program.parse(process.argv);
89
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import AirPurifier from './AirPurifier.js';
2
+ import { LGThinQHomebridgePlatform } from '../platform.js';
3
+ import { CharacteristicValue, Logger, PlatformAccessory, Service } from 'homebridge';
4
+ import { Device } from '../lib/Device.js';
5
+ import { AccessoryContext } from '../baseDevice.js';
6
+ export declare enum LightBrightness {
7
+ OFF = 0,
8
+ ON = 1,
9
+ LEVEL_1 = 8,
10
+ LEVEL_2 = 9,
11
+ LEVEL_3 = 10
12
+ }
13
+ export default class AeroTower extends AirPurifier {
14
+ readonly platform: LGThinQHomebridgePlatform;
15
+ readonly accessory: PlatformAccessory<AccessoryContext>;
16
+ protected serviceTemperatureSensor: Service;
17
+ protected serviceHumiditySensor: Service;
18
+ protected serviceUVNano: Service;
19
+ constructor(platform: LGThinQHomebridgePlatform, accessory: PlatformAccessory<AccessoryContext>, logger: Logger);
20
+ setLight(value: CharacteristicValue): Promise<void>;
21
+ protected setUVMode(value: CharacteristicValue): Promise<void>;
22
+ protected setLightBrightness(value: CharacteristicValue): Promise<void>;
23
+ updateAccessoryCharacteristic(device: Device): void;
24
+ }
@@ -0,0 +1,113 @@
1
+ import AirPurifier from './AirPurifier.js';
2
+ import { normalizeNumber } from '../helper.js';
3
+ export var LightBrightness;
4
+ (function (LightBrightness) {
5
+ LightBrightness[LightBrightness["OFF"] = 0] = "OFF";
6
+ LightBrightness[LightBrightness["ON"] = 1] = "ON";
7
+ LightBrightness[LightBrightness["LEVEL_1"] = 8] = "LEVEL_1";
8
+ LightBrightness[LightBrightness["LEVEL_2"] = 9] = "LEVEL_2";
9
+ LightBrightness[LightBrightness["LEVEL_3"] = 10] = "LEVEL_3";
10
+ })(LightBrightness || (LightBrightness = {}));
11
+ export default class AeroTower extends AirPurifier {
12
+ platform;
13
+ accessory;
14
+ serviceTemperatureSensor;
15
+ serviceHumiditySensor;
16
+ serviceUVNano;
17
+ constructor(platform, accessory, logger) {
18
+ super(platform, accessory, logger);
19
+ this.platform = platform;
20
+ this.accessory = accessory;
21
+ const { Service: { TemperatureSensor, HumiditySensor, Switch, }, Characteristic, } = this.platform;
22
+ this.serviceTemperatureSensor = this.getOrCreateService(TemperatureSensor, 'Temperature Sensor');
23
+ this.serviceHumiditySensor = this.getOrCreateService(HumiditySensor, 'Humidity Sensor');
24
+ this.serviceLight?.getCharacteristic(Characteristic.Brightness)
25
+ .setProps({
26
+ maxValue: 3, // 3 level of light
27
+ })
28
+ .onSet(this.setLightBrightness.bind(this));
29
+ this.serviceUVNano = this.getOrCreateService(Switch, 'UV Purifier', 'UV Purifier');
30
+ this.serviceUVNano.getCharacteristic(Characteristic.On).onSet(this.setUVMode.bind(this));
31
+ }
32
+ async setLight(value) {
33
+ if (!this.Status.isPowerOn) {
34
+ return;
35
+ }
36
+ const device = this.accessory.context.device;
37
+ const isLightOn = value ? 1 : 0;
38
+ try {
39
+ const result = await this.platform.ThinQ?.deviceControl(device.id, {
40
+ dataKey: 'airState.lightingState.displayControl',
41
+ dataValue: isLightOn,
42
+ });
43
+ if (result) {
44
+ device.data.snapshot['airState.lightingState.displayControl'] = isLightOn;
45
+ this.updateAccessoryCharacteristic(device);
46
+ }
47
+ }
48
+ catch (error) {
49
+ this.logger.error('Error setting light state:', error);
50
+ }
51
+ }
52
+ async setUVMode(value) {
53
+ const device = this.accessory.context.device;
54
+ const uvModeValue = value ? 1 : 0;
55
+ try {
56
+ const result = await this.platform.ThinQ?.deviceControl(device.id, {
57
+ dataKey: 'airState.miscFuncState.Uvnano',
58
+ dataValue: uvModeValue,
59
+ });
60
+ if (result) {
61
+ device.data.snapshot['airState.miscFuncState.Uvnano'] = uvModeValue;
62
+ this.updateAccessoryCharacteristic(device);
63
+ }
64
+ }
65
+ catch (error) {
66
+ this.logger.error('Error setting UV mode:', error);
67
+ }
68
+ }
69
+ async setLightBrightness(value) {
70
+ const vNum = normalizeNumber(value);
71
+ if (vNum === null) {
72
+ return;
73
+ }
74
+ const device = this.accessory.context.device;
75
+ const brightnessValue = vNum - 1;
76
+ const values = [LightBrightness.LEVEL_1, LightBrightness.LEVEL_2, LightBrightness.LEVEL_3];
77
+ if (typeof values[brightnessValue] !== 'undefined') {
78
+ try {
79
+ const result = await this.platform.ThinQ?.deviceControl(device.id, {
80
+ dataKey: 'airState.lightingState.displayControl',
81
+ dataValue: values[brightnessValue],
82
+ });
83
+ if (result) {
84
+ device.data.snapshot['airState.lightingState.displayControl'] = values[brightnessValue];
85
+ this.updateAccessoryCharacteristic(device);
86
+ }
87
+ }
88
+ catch (error) {
89
+ this.logger.error('Error setting light brightness:', error);
90
+ }
91
+ }
92
+ }
93
+ updateAccessoryCharacteristic(device) {
94
+ super.updateAccessoryCharacteristic(device);
95
+ const { Characteristic, } = this.platform;
96
+ const snapshot = device.data.snapshot;
97
+ // light brightness
98
+ const values = [LightBrightness.LEVEL_1, LightBrightness.LEVEL_2, LightBrightness.LEVEL_3];
99
+ const brightnessValue = values.indexOf(snapshot['airState.lightingState.displayControl'] || 0);
100
+ if (brightnessValue !== -1) {
101
+ this.serviceLight?.updateCharacteristic(Characteristic.Brightness, brightnessValue + 1);
102
+ }
103
+ if (typeof snapshot['airState.tempState.current'] !== 'undefined') {
104
+ this.serviceTemperatureSensor.updateCharacteristic(Characteristic.CurrentTemperature, snapshot['airState.tempState.current']);
105
+ }
106
+ if (typeof snapshot['airState.humidity.current'] !== 'undefined') {
107
+ this.serviceHumiditySensor.updateCharacteristic(Characteristic.CurrentRelativeHumidity, snapshot['airState.humidity.current']);
108
+ }
109
+ // uv mode
110
+ this.serviceUVNano.updateCharacteristic(Characteristic.On, !!(snapshot['airState.miscFuncState.Uvnano'] || 0));
111
+ }
112
+ }
113
+ //# sourceMappingURL=AeroTower.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AeroTower.js","sourceRoot":"","sources":["../../src/devices/AeroTower.ts"],"names":[],"mappings":"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"}