iobroker.acinfinity 0.7.1 → 0.7.3
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/admin/jsonConfig.json +32 -70
- package/io-package.json +28 -2
- package/lib/client.js +84 -54
- package/lib/constants.js +96 -108
- package/lib/creators/deviceCreator.js +97 -91
- package/lib/creators/portCreator.js +238 -225
- package/lib/creators/stateCreator.js +27 -21
- package/lib/dataModels.js +25 -20
- package/lib/handlers/deviceSettingsHandler.js +55 -38
- package/lib/handlers/portModeHandler.js +72 -71
- package/lib/handlers/portSettingsHandler.js +95 -68
- package/lib/stateManager.js +62 -42
- package/lib/updaters/deviceUpdater.js +133 -96
- package/lib/updaters/portUpdater.js +256 -207
- package/main.js +102 -77
- package/package.json +4 -4
package/admin/jsonConfig.json
CHANGED
|
@@ -2,76 +2,38 @@
|
|
|
2
2
|
"i18n": true,
|
|
3
3
|
"type": "panel",
|
|
4
4
|
"items": {
|
|
5
|
-
"
|
|
6
|
-
"type": "
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"fontSize": "18px",
|
|
14
|
-
"fontWeight": "bold",
|
|
15
|
-
"textAlign": "center"
|
|
16
|
-
},
|
|
17
|
-
"sm": 12,
|
|
18
|
-
"md": 12,
|
|
19
|
-
"lg": 12,
|
|
20
|
-
"xl": 12,
|
|
21
|
-
"xs": 12
|
|
22
|
-
},
|
|
23
|
-
"warningText": {
|
|
24
|
-
"type": "staticText",
|
|
25
|
-
"text": "This adapter is in an early development stage. You use this adapter at your own risk. The author assumes no liability for any damage.<br><br>Dieser Adapter befindet sich in einem frühen Entwicklungsstadium. Sie verwenden diesen Adapter auf eigene Gefahr. Der Autor übernimmt keine Haftung für eventuelle Schäden.",
|
|
26
|
-
"style": {
|
|
27
|
-
"color": "red",
|
|
28
|
-
"fontWeight": "bold",
|
|
29
|
-
"textAlign": "center",
|
|
30
|
-
"marginBottom": "20px"
|
|
31
|
-
},
|
|
32
|
-
"sm": 12,
|
|
33
|
-
"md": 12,
|
|
34
|
-
"lg": 12,
|
|
35
|
-
"xl": 12,
|
|
36
|
-
"xs": 12
|
|
37
|
-
}
|
|
38
|
-
}
|
|
5
|
+
"email": {
|
|
6
|
+
"type": "text",
|
|
7
|
+
"label": "AC Infinity Email",
|
|
8
|
+
"sm": 12,
|
|
9
|
+
"md": 8,
|
|
10
|
+
"lg": 6,
|
|
11
|
+
"xl": 6,
|
|
12
|
+
"xs": 12
|
|
39
13
|
},
|
|
40
|
-
"
|
|
41
|
-
"type": "
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"pollingInterval": {
|
|
64
|
-
"type": "number",
|
|
65
|
-
"label": "Polling Interval / Abfrageintervall (seconds)",
|
|
66
|
-
"min": 5,
|
|
67
|
-
"default": 30,
|
|
68
|
-
"sm": 12,
|
|
69
|
-
"md": 6,
|
|
70
|
-
"lg": 4,
|
|
71
|
-
"xl": 3,
|
|
72
|
-
"xs": 12
|
|
73
|
-
}
|
|
74
|
-
}
|
|
14
|
+
"password": {
|
|
15
|
+
"type": "password",
|
|
16
|
+
"label": "AC Infinity Password",
|
|
17
|
+
"help": "Note: AC Infinity truncates passwords to 25 characters.",
|
|
18
|
+
"newLine": true,
|
|
19
|
+
"sm": 12,
|
|
20
|
+
"md": 8,
|
|
21
|
+
"lg": 6,
|
|
22
|
+
"xl": 6,
|
|
23
|
+
"xs": 12
|
|
24
|
+
},
|
|
25
|
+
"pollingInterval": {
|
|
26
|
+
"type": "number",
|
|
27
|
+
"label": "Polling Interval (seconds)",
|
|
28
|
+
"help": "Minimum polling interval is 5 seconds.",
|
|
29
|
+
"newLine": true,
|
|
30
|
+
"min": 5,
|
|
31
|
+
"default": 30,
|
|
32
|
+
"sm": 6,
|
|
33
|
+
"md": 4,
|
|
34
|
+
"lg": 3,
|
|
35
|
+
"xl": 2,
|
|
36
|
+
"xs": 6
|
|
75
37
|
}
|
|
76
38
|
}
|
|
77
|
-
}
|
|
39
|
+
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "acinfinity",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.7.3": {
|
|
7
|
+
"en": "Admin UI: remove warning box, clean up settings layout, fix help link",
|
|
8
|
+
"de": "Admin-UI: Warnhinweis entfernt, Einstellungslayout bereinigt, Hilfe-Link korrigiert",
|
|
9
|
+
"ru": "Admin UI: убран блок предупреждения, улучшен макет настроек, исправлена ссылка на справку",
|
|
10
|
+
"pt": "Admin UI: caixa de aviso removida, layout de configurações limpo, link de ajuda corrigido",
|
|
11
|
+
"nl": "Admin UI: waarschuwingsvak verwijderd, instellingen layout verbeterd, helplink gecorrigeerd",
|
|
12
|
+
"fr": "Admin UI: bloc d'avertissement supprimé, mise en page des paramètres améliorée, lien d'aide corrigé",
|
|
13
|
+
"it": "Admin UI: riquadro di avviso rimosso, layout impostazioni migliorato, link guida corretto",
|
|
14
|
+
"es": "Admin UI: cuadro de advertencia eliminado, diseño de configuración mejorado, enlace de ayuda corregido",
|
|
15
|
+
"pl": "Admin UI: usunięto pole ostrzeżenia, poprawiono układ ustawień, naprawiono link pomocy",
|
|
16
|
+
"uk": "Admin UI: видалено блок попередження, покращено макет налаштувань, виправлено посилання на довідку",
|
|
17
|
+
"zh-cn": "管理界面:移除警告框,优化设置布局,修复帮助链接"
|
|
18
|
+
},
|
|
19
|
+
"0.7.2": {
|
|
20
|
+
"en": "Code quality: migrate to ESLint 9 with @iobroker/eslint-config",
|
|
21
|
+
"de": "Codequalität: Migration auf ESLint 9 mit @iobroker/eslint-config",
|
|
22
|
+
"ru": "Качество кода: миграция на ESLint 9 с @iobroker/eslint-config",
|
|
23
|
+
"pt": "Qualidade do código: migração para ESLint 9 com @iobroker/eslint-config",
|
|
24
|
+
"nl": "Codekwaliteit: migratie naar ESLint 9 met @iobroker/eslint-config",
|
|
25
|
+
"fr": "Qualité du code: migration vers ESLint 9 avec @iobroker/eslint-config",
|
|
26
|
+
"it": "Qualità del codice: migrazione a ESLint 9 con @iobroker/eslint-config",
|
|
27
|
+
"es": "Calidad del código: migración a ESLint 9 con @iobroker/eslint-config",
|
|
28
|
+
"pl": "Jakość kodu: migracja do ESLint 9 z @iobroker/eslint-config",
|
|
29
|
+
"uk": "Якість коду: міграція на ESLint 9 з @iobroker/eslint-config",
|
|
30
|
+
"zh-cn": "代码质量:迁移到 ESLint 9 并使用 @iobroker/eslint-config"
|
|
31
|
+
},
|
|
6
32
|
"0.7.1": {
|
|
7
33
|
"en": "Add value ranges to state names for better readability",
|
|
8
34
|
"de": "Wertebereiche zu Datenpunkt-Namen hinzugefügt für bessere Lesbarkeit",
|
|
@@ -137,7 +163,7 @@
|
|
|
137
163
|
"icon": "acinfinity.png",
|
|
138
164
|
"enabled": true,
|
|
139
165
|
"extIcon": "https://raw.githubusercontent.com/raspilaurent/ioBroker.acinfinity/master/admin/acinfinity.png",
|
|
140
|
-
"readme": "https://github.com/raspilaurent/ioBroker.acinfinity/blob/
|
|
166
|
+
"readme": "https://github.com/raspilaurent/ioBroker.acinfinity/blob/main/README.md",
|
|
141
167
|
"loglevel": "info",
|
|
142
168
|
"mode": "daemon",
|
|
143
169
|
"type": "climate-control",
|
package/lib/client.js
CHANGED
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
* Handles all API communication with AC Infinity servers
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
'use strict';
|
|
7
7
|
|
|
8
|
-
const axios = require(
|
|
9
|
-
const { API_BASE_URL, API_ENDPOINTS } = require(
|
|
8
|
+
const axios = require('axios');
|
|
9
|
+
const { API_BASE_URL, API_ENDPOINTS } = require('./constants');
|
|
10
10
|
|
|
11
11
|
class ACInfinityClient {
|
|
12
12
|
/**
|
|
13
13
|
* Creates a new AC Infinity API client
|
|
14
|
+
*
|
|
14
15
|
* @param {string} email - AC Infinity account email
|
|
15
16
|
* @param {string} password - AC Infinity account password
|
|
16
17
|
* @param {object} log - Logger object
|
|
@@ -22,19 +23,20 @@ class ACInfinityClient {
|
|
|
22
23
|
this.token = null;
|
|
23
24
|
this.axiosInstance = axios.create({
|
|
24
25
|
timeout: 30000,
|
|
25
|
-
validateStatus: status => status >= 200 && status < 300
|
|
26
|
+
validateStatus: status => status >= 200 && status < 300,
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Creates headers for API requests
|
|
32
|
+
*
|
|
31
33
|
* @param {boolean} useAuthToken - Whether to include authentication token
|
|
32
34
|
* @returns {object}
|
|
33
35
|
*/
|
|
34
36
|
createHeaders(useAuthToken = false) {
|
|
35
37
|
const headers = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
'User-Agent': 'ACController/1.8.5 (com.acinfinity.humiture; build:500; iOS 17.0.1) Alamofire/5.7.1',
|
|
39
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
|
38
40
|
};
|
|
39
41
|
if (useAuthToken && this.token) {
|
|
40
42
|
headers.token = this.token;
|
|
@@ -44,6 +46,7 @@ class ACInfinityClient {
|
|
|
44
46
|
|
|
45
47
|
/**
|
|
46
48
|
* Performs API login and obtains authentication token
|
|
49
|
+
*
|
|
47
50
|
* @returns {Promise<void>}
|
|
48
51
|
*/
|
|
49
52
|
async login() {
|
|
@@ -52,21 +55,21 @@ class ACInfinityClient {
|
|
|
52
55
|
const formData = `appEmail=${encodeURIComponent(this.email)}&appPasswordl=${encodeURIComponent(normalizedPassword)}`;
|
|
53
56
|
this.log.debug(`Login attempt with: ${this.email}`);
|
|
54
57
|
|
|
55
|
-
const response = await this.axiosInstance.post(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{ headers: this.createHeaders(false) }
|
|
59
|
-
);
|
|
58
|
+
const response = await this.axiosInstance.post(`${API_BASE_URL}${API_ENDPOINTS.LOGIN}`, formData, {
|
|
59
|
+
headers: this.createHeaders(false),
|
|
60
|
+
});
|
|
60
61
|
|
|
61
62
|
if (response.data && response.data.code === 200) {
|
|
62
63
|
this.token = response.data.data.appId;
|
|
63
|
-
this.log.debug(
|
|
64
|
+
this.log.debug('Login successful');
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
|
-
throw new Error(`Login failed: ${response.data ? response.data.msg :
|
|
67
|
+
throw new Error(`Login failed: ${response.data ? response.data.msg : 'Unknown error'}`);
|
|
67
68
|
} catch (error) {
|
|
68
69
|
if (error.response) {
|
|
69
|
-
throw new Error(
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Login failed with status ${error.response.status}: ${error.response.data ? error.response.data.msg : 'Unknown error'}`,
|
|
72
|
+
);
|
|
70
73
|
}
|
|
71
74
|
throw new Error(`Login failed: ${error.message}`);
|
|
72
75
|
}
|
|
@@ -74,6 +77,7 @@ class ACInfinityClient {
|
|
|
74
77
|
|
|
75
78
|
/**
|
|
76
79
|
* Checks if client is logged in
|
|
80
|
+
*
|
|
77
81
|
* @returns {boolean}
|
|
78
82
|
*/
|
|
79
83
|
isLoggedIn() {
|
|
@@ -82,6 +86,7 @@ class ACInfinityClient {
|
|
|
82
86
|
|
|
83
87
|
/**
|
|
84
88
|
* General API call with automatic re-login on 401
|
|
89
|
+
*
|
|
85
90
|
* @param {string} endpoint
|
|
86
91
|
* @param {object} data
|
|
87
92
|
* @param {boolean} needsAuth
|
|
@@ -95,21 +100,19 @@ class ACInfinityClient {
|
|
|
95
100
|
try {
|
|
96
101
|
const formData = Object.entries(data)
|
|
97
102
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
98
|
-
.join(
|
|
103
|
+
.join('&');
|
|
99
104
|
|
|
100
|
-
const response = await this.axiosInstance.post(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{ headers: this.createHeaders(needsAuth) }
|
|
104
|
-
);
|
|
105
|
+
const response = await this.axiosInstance.post(`${API_BASE_URL}${endpoint}`, formData, {
|
|
106
|
+
headers: this.createHeaders(needsAuth),
|
|
107
|
+
});
|
|
105
108
|
|
|
106
109
|
if (response.data && response.data.code === 200) {
|
|
107
110
|
return response.data.data || {};
|
|
108
111
|
}
|
|
109
|
-
throw new Error(`API call to ${endpoint} failed: ${response.data ? response.data.msg :
|
|
112
|
+
throw new Error(`API call to ${endpoint} failed: ${response.data ? response.data.msg : 'Unknown error'}`);
|
|
110
113
|
} catch (error) {
|
|
111
114
|
if (error.response && error.response.status === 401 && needsAuth) {
|
|
112
|
-
this.log.info(
|
|
115
|
+
this.log.info('Token expired, attempting to re-login');
|
|
113
116
|
await this.login();
|
|
114
117
|
return this.apiCall(endpoint, data, needsAuth);
|
|
115
118
|
}
|
|
@@ -122,6 +125,7 @@ class ACInfinityClient {
|
|
|
122
125
|
|
|
123
126
|
/**
|
|
124
127
|
* Gets list of all AC Infinity devices
|
|
128
|
+
*
|
|
125
129
|
* @returns {Promise<Array>}
|
|
126
130
|
*/
|
|
127
131
|
async getDevicesList() {
|
|
@@ -130,35 +134,46 @@ class ACInfinityClient {
|
|
|
130
134
|
|
|
131
135
|
/**
|
|
132
136
|
* Gets mode settings for a specific device port
|
|
137
|
+
*
|
|
133
138
|
* @param {string|number} deviceId
|
|
134
139
|
* @param {number} portId
|
|
135
140
|
* @returns {Promise<object>}
|
|
136
141
|
*/
|
|
137
142
|
async getDeviceModeSettings(deviceId, portId) {
|
|
138
143
|
this.log.debug(`Getting mode settings for deviceId=${deviceId}, portId=${portId}`);
|
|
139
|
-
return this.apiCall(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
return this.apiCall(
|
|
145
|
+
API_ENDPOINTS.DEVICE_MODE_SETTINGS,
|
|
146
|
+
{
|
|
147
|
+
devId: deviceId,
|
|
148
|
+
port: portId,
|
|
149
|
+
},
|
|
150
|
+
true,
|
|
151
|
+
);
|
|
143
152
|
}
|
|
144
153
|
|
|
145
154
|
/**
|
|
146
155
|
* Gets advanced settings for a device or port
|
|
156
|
+
*
|
|
147
157
|
* @param {string|number} deviceId
|
|
148
158
|
* @param {number} portId - 0 for controller-level settings
|
|
149
159
|
* @returns {Promise<object>}
|
|
150
160
|
*/
|
|
151
161
|
async getDeviceSettings(deviceId, portId) {
|
|
152
162
|
this.log.debug(`Getting device settings for deviceId=${deviceId}, portId=${portId}`);
|
|
153
|
-
return this.apiCall(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
163
|
+
return this.apiCall(
|
|
164
|
+
API_ENDPOINTS.DEVICE_SETTINGS,
|
|
165
|
+
{
|
|
166
|
+
devId: deviceId,
|
|
167
|
+
port: portId,
|
|
168
|
+
},
|
|
169
|
+
true,
|
|
170
|
+
);
|
|
157
171
|
}
|
|
158
172
|
|
|
159
173
|
/**
|
|
160
174
|
* Sends a raw URL-encoded form payload to the addDevMode endpoint.
|
|
161
175
|
* This is the single write path for all mode and speed changes.
|
|
176
|
+
*
|
|
162
177
|
* @param {string} formData - URL-encoded form data string
|
|
163
178
|
* @returns {Promise<boolean>}
|
|
164
179
|
*/
|
|
@@ -173,17 +188,17 @@ class ACInfinityClient {
|
|
|
173
188
|
const response = await this.axiosInstance.post(
|
|
174
189
|
`${API_BASE_URL}${API_ENDPOINTS.UPDATE_DEVICE_MODE}`,
|
|
175
190
|
formData,
|
|
176
|
-
{ headers: this.createHeaders(true) }
|
|
191
|
+
{ headers: this.createHeaders(true) },
|
|
177
192
|
);
|
|
178
193
|
|
|
179
194
|
if (response.data && response.data.code === 200) {
|
|
180
|
-
this.log.debug(
|
|
195
|
+
this.log.debug('Mode update successful');
|
|
181
196
|
return true;
|
|
182
197
|
}
|
|
183
|
-
throw new Error(`Mode update failed: ${response.data ? response.data.msg :
|
|
198
|
+
throw new Error(`Mode update failed: ${response.data ? response.data.msg : 'Unknown error'}`);
|
|
184
199
|
} catch (error) {
|
|
185
200
|
if (error.response && error.response.status === 401) {
|
|
186
|
-
this.log.info(
|
|
201
|
+
this.log.info('Token expired, re-logging in');
|
|
187
202
|
await this.login();
|
|
188
203
|
return this.sendRawModeUpdate(formData);
|
|
189
204
|
}
|
|
@@ -213,10 +228,10 @@ class ACInfinityClient {
|
|
|
213
228
|
|
|
214
229
|
const settings = await this.getDeviceModeSettings(deviceId, portId);
|
|
215
230
|
const modeSetid = settings.modeSetid;
|
|
216
|
-
const vpdnums =
|
|
231
|
+
const vpdnums = settings.vpdnums !== undefined && settings.vpdnums !== null ? settings.vpdnums : 0;
|
|
217
232
|
|
|
218
233
|
// speak = active speed; 0 when mode is Off (atType=1)
|
|
219
|
-
const speak =
|
|
234
|
+
const speak = atType === 2 ? onSpeed : 0;
|
|
220
235
|
|
|
221
236
|
const formData = [
|
|
222
237
|
`modeSetid=${encodeURIComponent(modeSetid)}`,
|
|
@@ -228,16 +243,19 @@ class ACInfinityClient {
|
|
|
228
243
|
`speak=${encodeURIComponent(speak)}`,
|
|
229
244
|
`curMode=${encodeURIComponent(atType)}`,
|
|
230
245
|
`vpdstatus=0`,
|
|
231
|
-
`vpdnums=${encodeURIComponent(vpdnums)}
|
|
232
|
-
].join(
|
|
246
|
+
`vpdnums=${encodeURIComponent(vpdnums)}`,
|
|
247
|
+
].join('&');
|
|
233
248
|
|
|
234
|
-
this.log.info(
|
|
249
|
+
this.log.info(
|
|
250
|
+
`setDeviceMode: deviceId=${deviceId}, portId=${portId}, atType=${atType}, onSpeed=${onSpeed}, offSpeed=${offSpeed}`,
|
|
251
|
+
);
|
|
235
252
|
return this.sendRawModeUpdate(formData);
|
|
236
253
|
}
|
|
237
254
|
|
|
238
255
|
/**
|
|
239
256
|
* Updates specific mode settings parameters (timer/cycle/auto/vpd/schedule values).
|
|
240
257
|
* Fetches current settings, applies overrides, and sends the full payload.
|
|
258
|
+
*
|
|
241
259
|
* @param {string|number} deviceId
|
|
242
260
|
* @param {number} portId
|
|
243
261
|
* @param {Array<Array<string|number>>} keyValues - Array of [key, value] pairs to override
|
|
@@ -255,23 +273,27 @@ class ACInfinityClient {
|
|
|
255
273
|
this.log.debug(`Current mode settings fetched for update`);
|
|
256
274
|
|
|
257
275
|
// Remove fields that the API rejects in write calls
|
|
258
|
-
const fieldsToRemove = [
|
|
276
|
+
const fieldsToRemove = ['devMacAddr', 'ipcSetting', 'devSetting'];
|
|
259
277
|
for (const field of fieldsToRemove) {
|
|
260
278
|
delete settings[field];
|
|
261
279
|
}
|
|
262
280
|
|
|
263
281
|
// Ensure required fields exist
|
|
264
|
-
if (!(
|
|
265
|
-
|
|
282
|
+
if (!('vpdstatus' in settings)) {
|
|
283
|
+
settings.vpdstatus = 0;
|
|
284
|
+
}
|
|
285
|
+
if (!('vpdnums' in settings)) {
|
|
286
|
+
settings.vpdnums = 0;
|
|
287
|
+
}
|
|
266
288
|
|
|
267
289
|
settings.devId = parseInt(deviceIdStr);
|
|
268
|
-
if (
|
|
290
|
+
if ('modeSetid' in settings) {
|
|
269
291
|
settings.modeSetid = String(settings.modeSetid);
|
|
270
292
|
}
|
|
271
293
|
|
|
272
294
|
// Apply the requested overrides
|
|
273
295
|
for (const [key, value] of keyValues) {
|
|
274
|
-
settings[key] =
|
|
296
|
+
settings[key] = typeof value === 'number' ? value : parseInt(String(value));
|
|
275
297
|
}
|
|
276
298
|
|
|
277
299
|
// Replace any remaining null/undefined with 0
|
|
@@ -283,13 +305,14 @@ class ACInfinityClient {
|
|
|
283
305
|
|
|
284
306
|
const formData = Object.entries(settings)
|
|
285
307
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
286
|
-
.join(
|
|
308
|
+
.join('&');
|
|
287
309
|
|
|
288
310
|
return this.sendRawModeUpdate(formData);
|
|
289
311
|
}
|
|
290
312
|
|
|
291
313
|
/**
|
|
292
314
|
* Updates advanced (device/port-level) settings
|
|
315
|
+
*
|
|
293
316
|
* @param {string|number} deviceId
|
|
294
317
|
* @param {number} portId - 0 for controller-level settings
|
|
295
318
|
* @param {string} deviceName - Device name (prevents API from resetting it to "None")
|
|
@@ -309,22 +332,29 @@ class ACInfinityClient {
|
|
|
309
332
|
settings.devName = deviceName;
|
|
310
333
|
|
|
311
334
|
const fieldsToRemove = [
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
335
|
+
'setId',
|
|
336
|
+
'devMacAddr',
|
|
337
|
+
'portResistance',
|
|
338
|
+
'devTimeZone',
|
|
339
|
+
'sensorSetting',
|
|
340
|
+
'sensorTransBuff',
|
|
341
|
+
'subDeviceVersion',
|
|
342
|
+
'secFucReportTime',
|
|
343
|
+
'updateAllPort',
|
|
344
|
+
'calibrationTime',
|
|
315
345
|
];
|
|
316
346
|
for (const field of fieldsToRemove) {
|
|
317
347
|
delete settings[field];
|
|
318
348
|
}
|
|
319
349
|
|
|
320
|
-
const stringFields = [
|
|
350
|
+
const stringFields = ['sensorTransBuffStr', 'sensorSettingStr', 'portParamData', 'paramSensors'];
|
|
321
351
|
for (const field of stringFields) {
|
|
322
352
|
if (!(field in settings) || settings[field] === null) {
|
|
323
|
-
settings[field] =
|
|
353
|
+
settings[field] = '';
|
|
324
354
|
}
|
|
325
355
|
}
|
|
326
356
|
|
|
327
|
-
const defaultFields = [
|
|
357
|
+
const defaultFields = ['sensorOneType', 'isShare', 'targetVpdSwitch', 'sensorTwoType', 'zoneSensorType'];
|
|
328
358
|
for (const field of defaultFields) {
|
|
329
359
|
if (!(field in settings)) {
|
|
330
360
|
settings[field] = 0;
|
|
@@ -345,12 +375,12 @@ class ACInfinityClient {
|
|
|
345
375
|
|
|
346
376
|
const formData = Object.entries(settings)
|
|
347
377
|
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
348
|
-
.join(
|
|
378
|
+
.join('&');
|
|
349
379
|
|
|
350
380
|
const response = await this.axiosInstance.post(
|
|
351
381
|
`${API_BASE_URL}${API_ENDPOINTS.UPDATE_ADVANCED_SETTINGS}`,
|
|
352
382
|
formData,
|
|
353
|
-
{ headers: this.createHeaders(true) }
|
|
383
|
+
{ headers: this.createHeaders(true) },
|
|
354
384
|
);
|
|
355
385
|
|
|
356
386
|
if (response.data && response.data.code === 200) {
|
|
@@ -358,7 +388,7 @@ class ACInfinityClient {
|
|
|
358
388
|
return;
|
|
359
389
|
}
|
|
360
390
|
|
|
361
|
-
throw new Error(`Failed to update advanced settings: ${response.data ? response.data.msg :
|
|
391
|
+
throw new Error(`Failed to update advanced settings: ${response.data ? response.data.msg : 'Unknown error'}`);
|
|
362
392
|
}
|
|
363
393
|
}
|
|
364
394
|
|