@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,141 @@
1
+ import { Session } from './Session.js';
2
+ import { Gateway } from './Gateway.js';
3
+ import { Auth } from './Auth.js';
4
+ import { WorkId } from './ThinQ.js';
5
+ import { Method } from 'axios';
6
+ import { Logger } from 'homebridge';
7
+ /**
8
+ * The `API` class provides methods to interact with the LG ThinQ API, enabling
9
+ * device management, home management, and command execution. It handles
10
+ * authentication, session management, and API requests with appropriate headers.
11
+ *
12
+ * @remarks
13
+ * This class includes methods for sending commands to devices, retrieving device
14
+ * and home information, and managing authentication tokens. It supports both
15
+ * ThinQ1 and ThinQ2 APIs.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const api = new API('US', 'en-US', logger);
20
+ * api.setUsernamePassword('username', 'password');
21
+ * await api.ready();
22
+ * const devices = await api.getListDevices();
23
+ * console.log(devices);
24
+ * ```
25
+ *
26
+ * @param country - The country code (default: 'US').
27
+ * @param language - The language code (default: 'en-US').
28
+ * @param logger - The logger instance for logging debug and error messages.
29
+ */
30
+ export declare class API {
31
+ protected country: string;
32
+ protected language: string;
33
+ protected logger: Logger;
34
+ protected _homes: any;
35
+ protected _gateway: Gateway | undefined;
36
+ protected session: Session;
37
+ protected jsessionId: string;
38
+ protected auth: Auth;
39
+ protected userNumber: string;
40
+ protected username: string;
41
+ protected password: string;
42
+ client_id: string;
43
+ httpClient: import("axios").AxiosInstance;
44
+ constructor(country: string | undefined, language: string | undefined, logger: Logger);
45
+ /**
46
+ * Sends a GET request to the specified URI.
47
+ *
48
+ * @param uri - The URI to send the GET request to.
49
+ * @returns A promise resolving to the response data.
50
+ * @throws Error if the URI is invalid.
51
+ */
52
+ getRequest(uri: string): Promise<any>;
53
+ /**
54
+ * Sends a POST request to the specified URI with the provided data.
55
+ *
56
+ * @param uri - The URI to send the POST request to.
57
+ * @param data - The data to include in the POST request.
58
+ * @returns A promise resolving to the response data.
59
+ */
60
+ postRequest(uri: string, data: any): Promise<any>;
61
+ resolveUrl(from: string, to: string): string;
62
+ /**
63
+ * Sends an HTTP request to the ThinQ API.
64
+ *
65
+ * @param method - The HTTP method ('get' or 'post').
66
+ * @param uri - The URI to send the request to.
67
+ * @param data - Optional data to include in the request.
68
+ * @param retry - Whether to retry the request in case of token expiration.
69
+ * @returns A promise resolving to the response data.
70
+ */
71
+ protected request(method: Method | undefined, uri: string, data?: any, retry?: boolean): Promise<any>;
72
+ protected get monitorHeaders(): Record<string, string>;
73
+ protected get defaultHeaders(): {
74
+ 'x-api-key': string;
75
+ 'x-thinq-app-ver': string;
76
+ 'x-thinq-app-type': string;
77
+ 'x-thinq-app-level': string;
78
+ 'x-thinq-app-os': string;
79
+ 'x-thinq-app-logintype': string;
80
+ 'x-service-code': string;
81
+ 'x-country-code': string;
82
+ 'x-language-code': string;
83
+ 'x-service-phase': string;
84
+ 'x-origin': string;
85
+ 'x-model-name': string;
86
+ 'x-os-version': string;
87
+ 'x-app-version': string;
88
+ 'x-message-id': string;
89
+ 'user-agent': string;
90
+ };
91
+ getSingleDevice(device_id: string): Promise<any>;
92
+ /**
93
+ * Retrieves the list of devices associated with the user's account.
94
+ *
95
+ * @returns A promise resolving to an array of devices.
96
+ */
97
+ getListDevices(): Promise<Record<string, any>[]>;
98
+ /**
99
+ * Retrieves the list of homes associated with the user's account.
100
+ *
101
+ * @returns A promise resolving to an array of homes.
102
+ */
103
+ getListHomes(): Promise<any>;
104
+ /**
105
+ * Sends a command to a specific device.
106
+ *
107
+ * @param device_id - The ID of the device to send the command to.
108
+ * @param values - The command values to send.
109
+ * @param command - The type of command ('Set' or 'Operation').
110
+ * @param ctrlKey - The control key (default: 'basicCtrl').
111
+ * @param ctrlPath - The control path (default: 'control-sync').
112
+ * @returns A promise resolving to the response of the command.
113
+ * @throws Error if `device_id` is not a valid non-empty string.
114
+ */
115
+ sendCommandToDevice(device_id: string, values: Record<string, any>, command: 'Set' | 'Operation', ctrlKey?: string, ctrlPath?: string): Promise<any>;
116
+ /**
117
+ * Sends a monitor command to a specific device.
118
+ *
119
+ * @param deviceId - The ID of the device to monitor.
120
+ * @param cmdOpt - The command option for monitoring.
121
+ * @param workId - The work ID associated with the monitoring command.
122
+ * @returns A promise resolving to the response of the monitor command.
123
+ * @throws Error if `deviceId` or `cmdOpt` is not a valid non-empty string.
124
+ */
125
+ sendMonitorCommand(deviceId: string, cmdOpt: string, workId: WorkId): Promise<any>;
126
+ /**
127
+ * Retrieves the monitor result for a specific device and work ID.
128
+ *
129
+ * @param device_id - The ID of the device.
130
+ * @param work_id - The work ID associated with the monitor result.
131
+ * @returns A promise resolving to the monitor result or null if not available.
132
+ * @throws Error if `device_id` or `work_id` is not a valid non-empty string.
133
+ */
134
+ getMonitorResult(device_id: string, work_id: string): Promise<Buffer<ArrayBuffer> | null>;
135
+ setRefreshToken(refreshToken: string): void;
136
+ setUsernamePassword(username: string, password: string): void;
137
+ gateway(): Promise<Gateway>;
138
+ ready(): Promise<void>;
139
+ refreshNewToken(session?: Session | null): Promise<void>;
140
+ thinq1PostRequest(endpoint: string, data: any): Promise<any>;
141
+ }
@@ -0,0 +1,362 @@
1
+ import * as constants from './constants.js';
2
+ import { URL } from 'url';
3
+ import { Session } from './Session.js';
4
+ import { Gateway } from './Gateway.js';
5
+ import { requestClient } from './request.js';
6
+ import { Auth } from './Auth.js';
7
+ import { ManualProcessNeeded, MonitorError, NotConnectedError, TokenExpiredError } from '../errors/index.js';
8
+ import crypto from 'crypto';
9
+ import axios from 'axios';
10
+ /**
11
+ * The `API` class provides methods to interact with the LG ThinQ API, enabling
12
+ * device management, home management, and command execution. It handles
13
+ * authentication, session management, and API requests with appropriate headers.
14
+ *
15
+ * @remarks
16
+ * This class includes methods for sending commands to devices, retrieving device
17
+ * and home information, and managing authentication tokens. It supports both
18
+ * ThinQ1 and ThinQ2 APIs.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const api = new API('US', 'en-US', logger);
23
+ * api.setUsernamePassword('username', 'password');
24
+ * await api.ready();
25
+ * const devices = await api.getListDevices();
26
+ * console.log(devices);
27
+ * ```
28
+ *
29
+ * @param country - The country code (default: 'US').
30
+ * @param language - The language code (default: 'en-US').
31
+ * @param logger - The logger instance for logging debug and error messages.
32
+ */
33
+ export class API {
34
+ country;
35
+ language;
36
+ logger;
37
+ _homes;
38
+ _gateway;
39
+ session = new Session('', '', 0);
40
+ jsessionId;
41
+ auth;
42
+ userNumber;
43
+ username;
44
+ password;
45
+ client_id;
46
+ httpClient = requestClient;
47
+ constructor(country = 'US', language = 'en-US', logger) {
48
+ this.country = country;
49
+ this.language = language;
50
+ this.logger = logger;
51
+ }
52
+ /**
53
+ * Sends a GET request to the specified URI.
54
+ *
55
+ * @param uri - The URI to send the GET request to.
56
+ * @returns A promise resolving to the response data.
57
+ * @throws Error if the URI is invalid.
58
+ */
59
+ async getRequest(uri) {
60
+ if (typeof uri !== 'string' || !uri.trim()) {
61
+ this.logger.error('Invalid URI: ', uri);
62
+ throw new Error('Invalid URI: URI must be a non-empty string.');
63
+ }
64
+ return await this.request('get', uri);
65
+ }
66
+ /**
67
+ * Sends a POST request to the specified URI with the provided data.
68
+ *
69
+ * @param uri - The URI to send the POST request to.
70
+ * @param data - The data to include in the POST request.
71
+ * @returns A promise resolving to the response data.
72
+ */
73
+ async postRequest(uri, data) {
74
+ return await this.request('post', uri, data);
75
+ }
76
+ resolveUrl(from, to) {
77
+ const url = new URL(to, from);
78
+ return url.href;
79
+ }
80
+ /**
81
+ * Sends an HTTP request to the ThinQ API.
82
+ *
83
+ * @param method - The HTTP method ('get' or 'post').
84
+ * @param uri - The URI to send the request to.
85
+ * @param data - Optional data to include in the request.
86
+ * @param retry - Whether to retry the request in case of token expiration.
87
+ * @returns A promise resolving to the response data.
88
+ */
89
+ async request(method, uri, data, retry = false) {
90
+ const gateway = await this.gateway();
91
+ // Determine the appropriate headers based on the URI
92
+ const requestHeaders = (gateway.thinq1_url && uri.startsWith(gateway.thinq1_url))
93
+ ? this.monitorHeaders
94
+ : this.defaultHeaders;
95
+ const url = this.resolveUrl(gateway.thinq2_url, uri);
96
+ try {
97
+ const res = await this.httpClient.request({
98
+ method,
99
+ url,
100
+ data,
101
+ headers: requestHeaders,
102
+ });
103
+ return res.data;
104
+ }
105
+ catch (err) {
106
+ // Handle token expiration and retry the request
107
+ if (err instanceof TokenExpiredError && !retry) {
108
+ try {
109
+ await this.refreshNewToken();
110
+ return await this.request(method, uri, data, true);
111
+ }
112
+ catch (refreshErr) {
113
+ this.logger.error('refresh new token error: ', refreshErr);
114
+ return {};
115
+ }
116
+ }
117
+ else if (err instanceof ManualProcessNeeded) {
118
+ // Handle manual process errors (e.g., new terms agreement)
119
+ this.logger.warn('Handling new term agreement... If you keep getting this message, ' + err.message);
120
+ try {
121
+ await this.auth.handleNewTerm(this.session.accessToken);
122
+ this.logger.warn('LG new term agreement is accepted.');
123
+ }
124
+ catch (termErr) {
125
+ this.logger.error(termErr);
126
+ }
127
+ if (!retry) {
128
+ // Retry the request once
129
+ return await this.request(method, uri, data, true);
130
+ }
131
+ else {
132
+ return {};
133
+ }
134
+ }
135
+ else {
136
+ // Log other errors
137
+ if (axios.isAxiosError(err)) {
138
+ this.logger.error('axios request error: ', err.response?.data, data);
139
+ this.logger.error(err.stack || 'No stack error');
140
+ }
141
+ else if (!(err instanceof NotConnectedError)) {
142
+ this.logger.error('request error: ', err);
143
+ }
144
+ return {};
145
+ }
146
+ }
147
+ }
148
+ get monitorHeaders() {
149
+ const monitorHeaders = {
150
+ 'Accept': 'application/json',
151
+ 'x-thinq-application-key': 'wideq',
152
+ 'x-thinq-security-key': 'nuts_securitykey',
153
+ };
154
+ if (typeof this.session?.accessToken === 'string') {
155
+ monitorHeaders['x-thinq-token'] = this.session?.accessToken;
156
+ }
157
+ if (this.jsessionId) {
158
+ monitorHeaders['x-thinq-jsessionId'] = this.jsessionId;
159
+ }
160
+ return monitorHeaders;
161
+ }
162
+ get defaultHeaders() {
163
+ function random_string(length) {
164
+ const result = [];
165
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
166
+ const charactersLength = characters.length;
167
+ for (let i = 0; i < length; i++) {
168
+ result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));
169
+ }
170
+ return result.join('');
171
+ }
172
+ const headers = {};
173
+ if (this.session.accessToken) {
174
+ headers['x-emp-token'] = this.session.accessToken;
175
+ }
176
+ if (this.userNumber) {
177
+ headers['x-user-no'] = this.userNumber;
178
+ }
179
+ headers['x-client-id'] = this.client_id || constants.API_CLIENT_ID;
180
+ return {
181
+ 'x-api-key': constants.API_KEY,
182
+ 'x-thinq-app-ver': '3.6.1200',
183
+ 'x-thinq-app-type': 'NUTS',
184
+ 'x-thinq-app-level': 'PRD',
185
+ 'x-thinq-app-os': 'ANDROID',
186
+ 'x-thinq-app-logintype': 'LGE',
187
+ 'x-service-code': 'SVC202',
188
+ 'x-country-code': this.country,
189
+ 'x-language-code': this.language,
190
+ 'x-service-phase': 'OP',
191
+ 'x-origin': 'app-native',
192
+ 'x-model-name': 'samsung/SM-G930L',
193
+ 'x-os-version': 'AOS/7.1.2',
194
+ 'x-app-version': 'LG ThinQ/3.6.12110',
195
+ 'x-message-id': random_string(22),
196
+ 'user-agent': 'okhttp/3.14.9',
197
+ ...headers,
198
+ };
199
+ }
200
+ async getSingleDevice(device_id) {
201
+ const data = await this.getRequest('service/devices/' + device_id);
202
+ return data.result;
203
+ }
204
+ /**
205
+ * Retrieves the list of devices associated with the user's account.
206
+ *
207
+ * @returns A promise resolving to an array of devices.
208
+ */
209
+ async getListDevices() {
210
+ const homes = await this.getListHomes();
211
+ const devices = [];
212
+ // Retrieve devices for each home
213
+ for (let i = 0; i < homes.length; i++) {
214
+ const resp = await this.getRequest('service/homes/' + homes[i].homeId);
215
+ devices.push(...resp.result.devices);
216
+ }
217
+ return devices;
218
+ }
219
+ /**
220
+ * Retrieves the list of homes associated with the user's account.
221
+ *
222
+ * @returns A promise resolving to an array of homes.
223
+ */
224
+ async getListHomes() {
225
+ if (!this._homes) {
226
+ const data = await this.getRequest('service/homes');
227
+ this._homes = data.result.item;
228
+ }
229
+ return this._homes;
230
+ }
231
+ /**
232
+ * Sends a command to a specific device.
233
+ *
234
+ * @param device_id - The ID of the device to send the command to.
235
+ * @param values - The command values to send.
236
+ * @param command - The type of command ('Set' or 'Operation').
237
+ * @param ctrlKey - The control key (default: 'basicCtrl').
238
+ * @param ctrlPath - The control path (default: 'control-sync').
239
+ * @returns A promise resolving to the response of the command.
240
+ * @throws Error if `device_id` is not a valid non-empty string.
241
+ */
242
+ async sendCommandToDevice(device_id, values, command, ctrlKey = 'basicCtrl', ctrlPath = 'control-sync') {
243
+ if (typeof device_id !== 'string' || !device_id.trim()) {
244
+ throw new Error('Invalid device_id: must be a non-empty string.');
245
+ }
246
+ if (typeof command !== 'string' || !['Set', 'Operation'].includes(command)) {
247
+ throw new Error('Invalid command: must be "Set" or "Operation".');
248
+ }
249
+ return await this.postRequest('service/devices/' + device_id + '/' + ctrlPath, {
250
+ ctrlKey,
251
+ 'command': command,
252
+ ...values,
253
+ });
254
+ }
255
+ /**
256
+ * Sends a monitor command to a specific device.
257
+ *
258
+ * @param deviceId - The ID of the device to monitor.
259
+ * @param cmdOpt - The command option for monitoring.
260
+ * @param workId - The work ID associated with the monitoring command.
261
+ * @returns A promise resolving to the response of the monitor command.
262
+ * @throws Error if `deviceId` or `cmdOpt` is not a valid non-empty string.
263
+ */
264
+ async sendMonitorCommand(deviceId, cmdOpt, workId) {
265
+ if (typeof deviceId !== 'string' || !deviceId.trim()) {
266
+ throw new Error('Invalid deviceId: must be a non-empty string.');
267
+ }
268
+ if (typeof cmdOpt !== 'string' || !cmdOpt.trim()) {
269
+ throw new Error('Invalid cmdOpt: must be a non-empty string.');
270
+ }
271
+ const data = {
272
+ cmd: 'Mon',
273
+ cmdOpt,
274
+ deviceId,
275
+ workId,
276
+ };
277
+ return await this.thinq1PostRequest('rti/rtiMon', data);
278
+ }
279
+ /**
280
+ * Retrieves the monitor result for a specific device and work ID.
281
+ *
282
+ * @param device_id - The ID of the device.
283
+ * @param work_id - The work ID associated with the monitor result.
284
+ * @returns A promise resolving to the monitor result or null if not available.
285
+ * @throws Error if `device_id` or `work_id` is not a valid non-empty string.
286
+ */
287
+ async getMonitorResult(device_id, work_id) {
288
+ if (typeof device_id !== 'string' || !device_id.trim()) {
289
+ throw new Error('Invalid device_id: must be a non-empty string.');
290
+ }
291
+ if (typeof work_id !== 'string' || !work_id.trim()) {
292
+ throw new Error('Invalid work_id: must be a non-empty string.');
293
+ }
294
+ const data = await this.thinq1PostRequest('rti/rtiResult', { workList: [{ deviceId: device_id, workId: work_id }] });
295
+ if (!('workList' in data) || !('returnCode' in data.workList)) {
296
+ return null;
297
+ }
298
+ const workList = data.workList;
299
+ if (workList.returnCode !== '0000') {
300
+ throw new MonitorError(data);
301
+ }
302
+ if (!('returnData' in workList)) {
303
+ return null;
304
+ }
305
+ return Buffer.from(workList.returnData, 'base64');
306
+ }
307
+ setRefreshToken(refreshToken) {
308
+ if (typeof refreshToken !== 'string' || !refreshToken.trim()) {
309
+ throw new Error('Invalid refreshToken: refreshToken must be a non-empty string.');
310
+ }
311
+ this.session = new Session('', refreshToken, 0);
312
+ }
313
+ setUsernamePassword(username, password) {
314
+ this.username = username;
315
+ this.password = password;
316
+ }
317
+ async gateway() {
318
+ if (!this._gateway) {
319
+ const res = await requestClient.get(constants.GATEWAY_URL, { headers: this.defaultHeaders });
320
+ this._gateway = new Gateway(res.data.result);
321
+ }
322
+ return this._gateway;
323
+ }
324
+ async ready() {
325
+ // get gateway first
326
+ const gateway = await this.gateway();
327
+ if (!this.auth) {
328
+ this.auth = new Auth(gateway, this.logger);
329
+ this.auth.logger = this.logger;
330
+ }
331
+ if (!this.session.hasToken() && this.username && this.password) {
332
+ this.session = await this.auth.login(this.username, this.password);
333
+ await this.refreshNewToken(this.session);
334
+ }
335
+ if (!this.session.hasValidToken() && !!this.session.refreshToken) {
336
+ await this.refreshNewToken(this.session);
337
+ }
338
+ if (!this.jsessionId) {
339
+ // get new jsessionid
340
+ this.jsessionId = await this.auth.getJSessionId(this.session.accessToken);
341
+ }
342
+ if (!this.userNumber) {
343
+ this.userNumber = await this.auth.getUserNumber(this.session?.accessToken);
344
+ }
345
+ if (!this.client_id) {
346
+ const hash = crypto.createHash('sha256');
347
+ this.client_id = hash.update(this.userNumber + (new Date()).getTime()).digest('hex');
348
+ }
349
+ }
350
+ async refreshNewToken(session = null) {
351
+ session = session || this.session;
352
+ this.session = await this.auth.refreshNewToken(session);
353
+ this.jsessionId = await this.auth.getJSessionId(this.session.accessToken);
354
+ }
355
+ async thinq1PostRequest(endpoint, data) {
356
+ const response = await this.postRequest(this._gateway?.thinq1_url + endpoint, {
357
+ lgedmRoot: data,
358
+ });
359
+ return response.lgedmRoot;
360
+ }
361
+ }
362
+ //# sourceMappingURL=API.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"API.js","sourceRoot":"","sources":["../../src/lib/API.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,55 @@
1
+ /* eslint-disable dot-notation */
2
+ import { API } from './API.js';
3
+ import { beforeEach, describe, expect, jest, test } from '@jest/globals';
4
+ describe('API', () => {
5
+ let api;
6
+ let mockLogger;
7
+ beforeEach(() => {
8
+ mockLogger = {
9
+ debug: jest.fn(),
10
+ info: jest.fn(),
11
+ warn: jest.fn(),
12
+ error: jest.fn(),
13
+ };
14
+ api = new API('EC', 'en-US', mockLogger);
15
+ });
16
+ test('should initialize with default values', () => {
17
+ expect(api).toBeDefined();
18
+ expect(api.client_id).toBeUndefined();
19
+ expect(api.httpClient).toBeDefined();
20
+ });
21
+ test('should set username and password', () => {
22
+ api.setUsernamePassword('testUser', 'testPass');
23
+ expect(api['username']).toBe('testUser');
24
+ expect(api['password']).toBe('testPass');
25
+ });
26
+ test('should set refresh token', () => {
27
+ api.setRefreshToken('testRefreshToken');
28
+ expect(api['session'].refreshToken).toBe('testRefreshToken');
29
+ });
30
+ test('should handle device list retrieval', async () => {
31
+ const mockHomes = [{ homeId: 'home1' }];
32
+ const mockDevices = [{ id: 'device1' }, { id: 'device2' }];
33
+ jest.spyOn(api, 'getListHomes').mockResolvedValueOnce(mockHomes);
34
+ jest.spyOn(api.httpClient, 'request').mockResolvedValueOnce({
35
+ data: { result: { devices: mockDevices } },
36
+ });
37
+ const devices = await api.getListDevices();
38
+ expect(devices).toEqual(mockDevices);
39
+ });
40
+ test('should send command to device', async () => {
41
+ const mockRequest = jest.spyOn(api.httpClient, 'request').mockResolvedValueOnce({ data: { success: true } });
42
+ const result = await api.sendCommandToDevice('device1', { key: 'value' }, 'Set');
43
+ expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({
44
+ method: 'post',
45
+ url: expect.stringContaining('/devices/device1/control-sync'),
46
+ data: expect.objectContaining({
47
+ ctrlKey: 'basicCtrl',
48
+ command: 'Set',
49
+ key: 'value',
50
+ }),
51
+ }));
52
+ expect(result).toEqual({ success: true });
53
+ });
54
+ });
55
+ //# sourceMappingURL=API.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"API.spec.js","sourceRoot":"","sources":["../../src/lib/API.spec.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEzE,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;IACnB,IAAI,GAAQ,CAAC;IACb,IAAI,UAAkB,CAAC;IAEvB,UAAU,CAAC,GAAG,EAAE;QACd,UAAU,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;YAChB,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACf,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACf,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;SACI,CAAC;QAEvB,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC5C,GAAG,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACpC,GAAG,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,SAAS,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAE3D,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,qBAAqB,CAAC;YAC1D,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;SAC3C,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,EAAE,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAE7G,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;QACjF,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CACtC,MAAM,CAAC,gBAAgB,CAAC;YACtB,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,MAAM,CAAC,gBAAgB,CAAC,+BAA+B,CAAC;YAC7D,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;gBAC5B,OAAO,EAAE,WAAW;gBACpB,OAAO,EAAE,KAAK;gBACd,GAAG,EAAE,OAAO;aACb,CAAC;SACH,CAAC,CACH,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}