padavan 2.1.0 → 2.2.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/README.md +4 -0
- package/bin/cli.js +49 -13
- package/package.json +1 -1
- package/src/constants.js +60 -12
- package/src/index.js +51 -34
package/README.md
CHANGED
|
@@ -70,6 +70,10 @@ The constructor accepts a config object with the following properties:
|
|
|
70
70
|
- **`exec(command)`**
|
|
71
71
|
Executes a system command via the web console emulator (`SystemCmd`).
|
|
72
72
|
*Returns:* Command output (stdout + stderr).
|
|
73
|
+
- **`sendAction(action, payload?)`**
|
|
74
|
+
Sends a low-level action to `apply.cgi`.
|
|
75
|
+
*Arguments:* `action` (string, e.g., `' Reboot '`), `payload` (data object).
|
|
76
|
+
*Returns:* Server response (command output or status).
|
|
73
77
|
- **`startReboot()`**
|
|
74
78
|
Reboots the router via HTTP command.
|
|
75
79
|
|
package/bin/cli.js
CHANGED
|
@@ -4,8 +4,8 @@ import yargs from 'yargs';
|
|
|
4
4
|
import { hideBin } from 'yargs/helpers';
|
|
5
5
|
import Padavan from '../src/index.js';
|
|
6
6
|
import { formatBytes, formatUptime } from '../src/utils/formatting.js';
|
|
7
|
-
import { DEFAULT_HTTP_CONFIG, DEFAULT_FIRMWARE_REPO,
|
|
8
|
-
/** @import {
|
|
7
|
+
import { DEFAULT_HTTP_CONFIG, DEFAULT_FIRMWARE_REPO, SYSTEM_ACTION, CONFIG_ACTION, SERVICE_ID, GROUP_ID, WIFI_BANDS } from '../src/constants.js';
|
|
8
|
+
/** @import { SystemAction, ConfigAction, ServiceId, GroupId, WifiBand } from '../src/constants.js' */
|
|
9
9
|
/** @import { ArgumentsCamelCase } from 'yargs' */
|
|
10
10
|
/** @import { Device, WifiNetwork, ChannelAnalysis } from '../src/index.js' */
|
|
11
11
|
|
|
@@ -28,6 +28,8 @@ import { DEFAULT_HTTP_CONFIG, DEFAULT_FIRMWARE_REPO, ACTION_MODE, SERVICE_ID, GR
|
|
|
28
28
|
* @property {string} [model]
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
+
const SYSTEM_ACTION_VALUES = Object.values(SYSTEM_ACTION);
|
|
32
|
+
const CONFIG_ACTION_VALUES = Object.values(CONFIG_ACTION);
|
|
31
33
|
const logInfo = (/** @type {string} */ msg) => console.error(msg);
|
|
32
34
|
|
|
33
35
|
/**
|
|
@@ -117,8 +119,8 @@ cli.command('traffic', 'Get traffic history', {}, async (/** @type {ArgumentsCam
|
|
|
117
119
|
// --- WIFI DOCTOR ---
|
|
118
120
|
|
|
119
121
|
cli.command('scan [band]', 'Scan Wi-Fi networks', (yargs) => {
|
|
120
|
-
return yargs.positional('band', { type: 'string', choices:
|
|
121
|
-
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {band:
|
|
122
|
+
return yargs.positional('band', { type: 'string', choices: WIFI_BANDS, default: WIFI_BANDS[0] });
|
|
123
|
+
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {band: WifiBand}>} */ argv) => {
|
|
122
124
|
const client = getClient(argv);
|
|
123
125
|
logInfo(`Scanning ${argv.band}GHz networks...`);
|
|
124
126
|
const networks = await client.startScan(argv.band);
|
|
@@ -131,8 +133,8 @@ cli.command('scan [band]', 'Scan Wi-Fi networks', (yargs) => {
|
|
|
131
133
|
});
|
|
132
134
|
|
|
133
135
|
cli.command('doctor [band]', 'Analyze Wi-Fi environment and recommend channel', (yargs) => {
|
|
134
|
-
return yargs.positional('band', { type: 'string', choices:
|
|
135
|
-
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {band:
|
|
136
|
+
return yargs.positional('band', { type: 'string', choices: WIFI_BANDS, default: WIFI_BANDS[0] });
|
|
137
|
+
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {band: WifiBand}>} */ argv) => {
|
|
136
138
|
const client = getClient(argv);
|
|
137
139
|
logInfo(`Scanning and analyzing ${argv.band}GHz spectrum...`);
|
|
138
140
|
const result = await client.getBestChannel(argv.band);
|
|
@@ -164,17 +166,17 @@ cli.command('set <pairs..>', 'Set parameters (key=value)', (yargs) => {
|
|
|
164
166
|
.option('action', {
|
|
165
167
|
type: 'string',
|
|
166
168
|
describe: 'Action mode',
|
|
167
|
-
default:
|
|
169
|
+
default: CONFIG_ACTION.APPLY.trim(),
|
|
170
|
+
choices: CONFIG_ACTION_VALUES.map(m => m.trim()),
|
|
168
171
|
coerce: (arg) => {
|
|
169
|
-
const clean = arg.trim();
|
|
170
|
-
const match =
|
|
172
|
+
const clean = arg.trim().toLowerCase();
|
|
173
|
+
const match = CONFIG_ACTION_VALUES.map(m => m.trim()).find(m => m.toLowerCase() === clean);
|
|
171
174
|
return match || arg;
|
|
172
|
-
}
|
|
173
|
-
choices: ACTION_MODE.map(m => m.trim())
|
|
175
|
+
}
|
|
174
176
|
})
|
|
175
177
|
.example('$0 set rt_ssid=MyWifi --page "Advanced_WAdvanced_Content.asp"', 'Apply settings via Web UI')
|
|
176
178
|
.example('$0 set "rt_ACLList=AA:BB:CC:DD:EE:FF" --action Add --group rt_ACLList', 'Add MAC to filter');
|
|
177
|
-
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {pairs: string[], sid?: string|ServiceId[], page?: string, action?:
|
|
179
|
+
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {pairs: string[], sid?: string|ServiceId[], page?: string, action?: ConfigAction, group?: GroupId, script?: string}>} */ argv) => {
|
|
178
180
|
const client = getClient(argv);
|
|
179
181
|
const /** @type {Record<string, string>} */ params = {};
|
|
180
182
|
argv.pairs.forEach(p => {
|
|
@@ -182,7 +184,7 @@ cli.command('set <pairs..>', 'Set parameters (key=value)', (yargs) => {
|
|
|
182
184
|
if (k)
|
|
183
185
|
params[k] = v.join('=');
|
|
184
186
|
});
|
|
185
|
-
const action_mode =
|
|
187
|
+
const action_mode = CONFIG_ACTION_VALUES.find(m => m.trim() === argv.action) || argv.action;
|
|
186
188
|
await client.setParams(params, {
|
|
187
189
|
action_mode,
|
|
188
190
|
action_script: argv.script,
|
|
@@ -193,6 +195,40 @@ cli.command('set <pairs..>', 'Set parameters (key=value)', (yargs) => {
|
|
|
193
195
|
logInfo('Settings applied successfully.');
|
|
194
196
|
});
|
|
195
197
|
|
|
198
|
+
cli.command('call <action> [payload...]', 'Call a system action', (yargs) => {
|
|
199
|
+
return yargs
|
|
200
|
+
.positional('action', {
|
|
201
|
+
describe: 'System action to execute',
|
|
202
|
+
choices: SYSTEM_ACTION_VALUES.map(v => v.trim()),
|
|
203
|
+
coerce: (arg) => {
|
|
204
|
+
const clean = arg.trim().toLowerCase();
|
|
205
|
+
const match = SYSTEM_ACTION_VALUES.map(m => m.trim()).find(v => v.toLowerCase() === clean);
|
|
206
|
+
return match;
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
.example('$0 call SystemCmd ls -la /tmp', 'Execute a shell command')
|
|
210
|
+
.example('$0 call wg_action action=genkey', 'Pass payload for wg_action');
|
|
211
|
+
}, async (/** @type {ArgumentsCamelCase<CommonArgs & {action: SystemAction, payload?: string[]}>} */ argv) => {
|
|
212
|
+
const client = getClient(argv);
|
|
213
|
+
const action = SYSTEM_ACTION_VALUES.find(m => m.trim() === argv.action) || argv.action;
|
|
214
|
+
const payload = {};
|
|
215
|
+
if (argv.payload && argv.payload.length > 0) {
|
|
216
|
+
if (action === SYSTEM_ACTION.SYSTEM_CMD)
|
|
217
|
+
payload.SystemCmd = argv.payload.join(' ');
|
|
218
|
+
else
|
|
219
|
+
argv.payload.forEach(p => {
|
|
220
|
+
const [key, ...valParts] = p.split('=');
|
|
221
|
+
if (key)
|
|
222
|
+
payload[key] = valParts.join('=');
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
logInfo(`Executing action: ${action.trim()}`);
|
|
226
|
+
if (Object.keys(payload).length > 0)
|
|
227
|
+
logInfo(`With payload: ${JSON.stringify(payload)}`);
|
|
228
|
+
const result = await client.sendAction(action, payload);
|
|
229
|
+
printOutput(argv, result);
|
|
230
|
+
});
|
|
231
|
+
|
|
196
232
|
// --- FIRMWARE ---
|
|
197
233
|
|
|
198
234
|
cli.command('firmware <action>', 'Manage firmware', (yargs) => {
|
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -32,17 +32,57 @@ export const NVRAM_CACHE_TTL = 3_000;
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Режимы действия для apply.cgi.
|
|
35
|
-
*
|
|
36
|
-
* @typedef {(typeof ACTION_MODE)[number]} ActionMode
|
|
35
|
+
* @typedef {(typeof SYSTEM_ACTION)[keyof typeof SYSTEM_ACTION]} SystemAction
|
|
37
36
|
*/
|
|
38
|
-
export const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'
|
|
45
|
-
|
|
37
|
+
export const SYSTEM_ACTION = /** @type {const} */ ({
|
|
38
|
+
/** Полная перезагрузка роутера */
|
|
39
|
+
REBOOT: ' Reboot ',
|
|
40
|
+
/** Выключение роутера */
|
|
41
|
+
SHUTDOWN: ' Shutdown ',
|
|
42
|
+
/** Очистить системный лог */
|
|
43
|
+
CLEAR_LOG: ' ClearLog ',
|
|
44
|
+
/** Выполнить системную команду */
|
|
45
|
+
SYSTEM_CMD: ' SystemCmd ',
|
|
46
|
+
/** Сохранить NVRAM во флеш-память */
|
|
47
|
+
COMMIT_FLASH: ' CommitFlash ',
|
|
48
|
+
/** Сброс настроек к заводским */
|
|
49
|
+
RESTORE_NVRAM: ' RestoreNVRAM ',
|
|
50
|
+
/** Восстановить /etc/storage из сжатого файла */
|
|
51
|
+
RESTORE_STORAGE: ' RestoreStorage ',
|
|
52
|
+
/** Сбросить кэши памяти */
|
|
53
|
+
FREE_MEMORY: ' FreeMemory ',
|
|
54
|
+
/** Принудительная синхронизация времени */
|
|
55
|
+
NTP_SYNC_NOW: ' NTPSyncNow ',
|
|
56
|
+
/** Генерировать сертификат для HTTPS */
|
|
57
|
+
CREATE_CERT_HTTPS: ' CreateCertHTTPS ',
|
|
58
|
+
/** Проверка наличия SSL сертификата */
|
|
59
|
+
CHECK_CERT_HTTPS: ' CheckCertHTTPS ',
|
|
60
|
+
/** Генерировать ключи/сертификаты для OpenVPN сервера */
|
|
61
|
+
CREATE_CERT_OVPNS: ' CreateCertOVPNS ',
|
|
62
|
+
/** Экспорт конфига OpenVPN клиента */
|
|
63
|
+
EXPORT_CONF_OVPNC: ' ExportConfOVPNC ',
|
|
64
|
+
/** Экспорт конфига WireGuard */
|
|
65
|
+
EXPORT_WG_CONF: ' ExportWGConf ',
|
|
66
|
+
/** Действия WireGuard (требует доп. параметр action: genkey, pubkey, genpsk). */
|
|
67
|
+
WG_ACTION: ' wg_action '
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Режимы действия для start_apply.htm.
|
|
72
|
+
* @typedef {(typeof CONFIG_ACTION)[keyof typeof CONFIG_ACTION]} ConfigAction
|
|
73
|
+
*/
|
|
74
|
+
export const CONFIG_ACTION = /** @type {const} */ ({
|
|
75
|
+
/** Применить настройки (без перезагрузки всего роутера, если возможно) */
|
|
76
|
+
APPLY: ' Apply ',
|
|
77
|
+
/** Применить настройки с явным перезапуском связанных сервисов */
|
|
78
|
+
RESTART: ' Restart ',
|
|
79
|
+
/** Добавить запись в список (используется с group_id) */
|
|
80
|
+
ADD: ' Add ',
|
|
81
|
+
/** Удалить запись из списка (используется с group_id) */
|
|
82
|
+
DEL: ' Del ',
|
|
83
|
+
/** Используется в связке с action_script (например, для обновления DDNS или статуса принтера) */
|
|
84
|
+
UPDATE: 'Update'
|
|
85
|
+
});
|
|
46
86
|
|
|
47
87
|
/**
|
|
48
88
|
* Идентификаторы сервисов (Service ID).
|
|
@@ -66,6 +106,12 @@ export const GROUP_ID = /** @type {const} */ ([
|
|
|
66
106
|
'LWFilterList', 'VPNSACLList'
|
|
67
107
|
]);
|
|
68
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Диапазоны Wi-Fi.
|
|
111
|
+
* @typedef {(typeof WIFI_BANDS)[number]} WifiBand
|
|
112
|
+
*/
|
|
113
|
+
export const WIFI_BANDS = /** @type {const} */ (['2.4', '5']);
|
|
114
|
+
|
|
69
115
|
/** Системные команды роутера. */
|
|
70
116
|
export const COMMANDS = {
|
|
71
117
|
NVRAM_SHOW: 'nvram showall'
|
|
@@ -93,6 +139,8 @@ export const PAGES = {
|
|
|
93
139
|
SYSLOG: 'Main_LogStatus_Content.asp',
|
|
94
140
|
/** Страница обновления прошивки (POST) */
|
|
95
141
|
UPGRADE: 'upgrade.cgi',
|
|
96
|
-
/**
|
|
97
|
-
APPLY: 'apply.cgi'
|
|
142
|
+
/** Обработчик мгновенных действий (Reboot, Shell, AJAX) без редиректа */
|
|
143
|
+
APPLY: 'apply.cgi',
|
|
144
|
+
/** Обработчик применения настроек с сохранением NVRAM и перезапуском сервисов */
|
|
145
|
+
START_APPLY: 'start_apply.htm'
|
|
98
146
|
};
|
package/src/index.js
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
parsePageInputs, parseNvramOutput, parseLooseJson, normalizeTrafficHistory,
|
|
8
8
|
extractJsVariable, extractTextareaValue, extractMacsFromTextarea, extractCurrentChannel
|
|
9
9
|
} from './utils/parsers.js';
|
|
10
|
-
import { LOG_LEVELS, DEFAULT_LOG_LEVEL, LIB_ID, NVRAM_CACHE_TTL, PAGES, COMMANDS } from './constants.js';
|
|
11
|
-
/** @import {
|
|
10
|
+
import { LOG_LEVELS, DEFAULT_LOG_LEVEL, LIB_ID, NVRAM_CACHE_TTL, SYSTEM_ACTION, PAGES, COMMANDS } from './constants.js';
|
|
11
|
+
/** @import { SystemAction, ConfigAction, ServiceId, GroupId, WifiBand } from './constants.js' */
|
|
12
12
|
/** @import { Config as HttpConfig } from './transport/http.js' */
|
|
13
13
|
/** @import { Config as GithubConfig } from './transport/github.js' */
|
|
14
14
|
/** @typedef {HttpConfig & GithubConfig} Credentials */
|
|
@@ -52,7 +52,7 @@ import { LOG_LEVELS, DEFAULT_LOG_LEVEL, LIB_ID, NVRAM_CACHE_TTL, PAGES, COMMANDS
|
|
|
52
52
|
* @property {string} [next_page] Страница перенаправления.
|
|
53
53
|
* @property {string|ServiceId[]} [sid_list] Строка или массив сервисов для перезапуска.
|
|
54
54
|
* @property {GroupId} [group_id] ID группы.
|
|
55
|
-
* @property {
|
|
55
|
+
* @property {ConfigAction} [action_mode=' Apply '] Режим действия.
|
|
56
56
|
* @property {string} [action_script] Имя скрипта.
|
|
57
57
|
*/
|
|
58
58
|
|
|
@@ -150,24 +150,7 @@ export default class Padavan {
|
|
|
150
150
|
* @returns {Promise<string>} Вывод команды (stdout + stderr).
|
|
151
151
|
*/
|
|
152
152
|
async exec(command) {
|
|
153
|
-
|
|
154
|
-
this.log('debug', `Executing command: ${command}`);
|
|
155
|
-
if (!this.#http)
|
|
156
|
-
throw new Error('HTTP client not initialized');
|
|
157
|
-
try {
|
|
158
|
-
await this.#http.post(PAGES.APPLY, {
|
|
159
|
-
action_mode: ' SystemCmd ',
|
|
160
|
-
SystemCmd: command
|
|
161
|
-
});
|
|
162
|
-
const response = await this.#http.get(PAGES.CONSOLE_RESPONSE);
|
|
163
|
-
return response.trim();
|
|
164
|
-
} catch (e) {
|
|
165
|
-
this.log('error', `Command execution failed: ${command}`, e);
|
|
166
|
-
throw e;
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
this.#commandQueue = result.catch(() => {});
|
|
170
|
-
return result;
|
|
153
|
+
return this.sendAction(SYSTEM_ACTION.SYSTEM_CMD, { SystemCmd: command });
|
|
171
154
|
};
|
|
172
155
|
|
|
173
156
|
/**
|
|
@@ -224,19 +207,25 @@ export default class Padavan {
|
|
|
224
207
|
const kvPairs = Object.entries(params);
|
|
225
208
|
if (kvPairs.length === 0)
|
|
226
209
|
return;
|
|
210
|
+
|
|
227
211
|
const page = options.current_page || options.next_page;
|
|
212
|
+
let sid_list = options.sid_list;
|
|
213
|
+
let group_id = options.group_id || '';
|
|
228
214
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
else if (!sidList && page) {
|
|
215
|
+
if (Array.isArray(sid_list))
|
|
216
|
+
sid_list = sid_list.join(';') + ';';
|
|
217
|
+
else if (!sid_list && page) {
|
|
233
218
|
this.log('debug', `sid_list not provided, searching on ${page}...`);
|
|
234
219
|
try {
|
|
235
220
|
const html = await this.#http.get(page);
|
|
236
221
|
const pageInputs = parsePageInputs(html);
|
|
237
222
|
if (pageInputs['sid_list']) {
|
|
238
|
-
|
|
239
|
-
this.log('debug', `Found sid_list: ${
|
|
223
|
+
sid_list = pageInputs['sid_list'];
|
|
224
|
+
this.log('debug', `Found sid_list: ${sid_list}`);
|
|
225
|
+
if (!group_id && pageInputs['group_id']) {
|
|
226
|
+
group_id = pageInputs['group_id'];
|
|
227
|
+
this.log('debug', `Auto-detected group_id: ${group_id}`);
|
|
228
|
+
}
|
|
240
229
|
} else
|
|
241
230
|
this.log('warn', `Could not find sid_list on ${page}`);
|
|
242
231
|
} catch (e) {
|
|
@@ -248,18 +237,18 @@ export default class Padavan {
|
|
|
248
237
|
this.#nvramPromise = null;
|
|
249
238
|
this.#nvramTimestamp = 0;
|
|
250
239
|
|
|
251
|
-
if (
|
|
240
|
+
if (sid_list) {
|
|
252
241
|
const data = {
|
|
242
|
+
sid_list, group_id,
|
|
253
243
|
action_mode: options.action_mode || ' Apply ',
|
|
254
244
|
action_script: options.action_script || '',
|
|
255
|
-
sid_list: sidList,
|
|
256
|
-
group_id: options.group_id || '',
|
|
257
245
|
current_page: page || 'index.asp',
|
|
258
246
|
next_page: options.next_page || page || 'index.asp',
|
|
259
247
|
...params
|
|
260
248
|
};
|
|
249
|
+
this.log('debug', `POST ${PAGES.START_APPLY} payload:`, data);
|
|
261
250
|
try {
|
|
262
|
-
await this.#http.post(PAGES.
|
|
251
|
+
await this.#http.post(PAGES.START_APPLY, data);
|
|
263
252
|
return true;
|
|
264
253
|
} catch (e) {
|
|
265
254
|
this.log('debug', 'setParams (UI) finished', e.message);
|
|
@@ -278,6 +267,34 @@ export default class Padavan {
|
|
|
278
267
|
return true;
|
|
279
268
|
};
|
|
280
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Отправляет системную команду на apply.cgi и возвращает результат.
|
|
272
|
+
* @param {SystemAction} action Режим действия.
|
|
273
|
+
* @param {Object} [payload] Дополнительные данные.
|
|
274
|
+
* @returns {Promise<string>} Тело ответа от сервера.
|
|
275
|
+
*/
|
|
276
|
+
async sendAction(action, payload = {}) {
|
|
277
|
+
const result = this.#commandQueue.then(async () => {
|
|
278
|
+
this.log('info', `Sending system action: ${action}`);
|
|
279
|
+
try {
|
|
280
|
+
const result = await this.#http.post(PAGES.APPLY, {
|
|
281
|
+
action_mode: action,
|
|
282
|
+
...payload
|
|
283
|
+
});
|
|
284
|
+
if (action === SYSTEM_ACTION.SYSTEM_CMD) {
|
|
285
|
+
const response = await this.#http.get(PAGES.CONSOLE_RESPONSE);
|
|
286
|
+
return response.trim();
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
} catch (e) {
|
|
290
|
+
this.log('error', `Sending system action failed: ${action}`, e);
|
|
291
|
+
throw e;
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
this.#commandQueue = result.catch(() => {});
|
|
295
|
+
return result;
|
|
296
|
+
};
|
|
297
|
+
|
|
281
298
|
/**
|
|
282
299
|
* Получает текущий статус системы (CPU, RAM, Uptime, LoadAvg).
|
|
283
300
|
* @returns {Promise<Object>}
|
|
@@ -376,7 +393,7 @@ export default class Padavan {
|
|
|
376
393
|
/**
|
|
377
394
|
* Сканирование эфира.
|
|
378
395
|
* ВНИМАНИЕ: Если вы подключены по Wi-Fi к сканируемому диапазону, соединение разорвется.
|
|
379
|
-
* @param {
|
|
396
|
+
* @param {WifiBand} [band='2.4'] Частотный диапазон.
|
|
380
397
|
* @returns {Promise<WifiNetwork[]>} Список найденных сетей, отсортированный по уровню сигнала.
|
|
381
398
|
*/
|
|
382
399
|
async startScan(band = '2.4') {
|
|
@@ -409,7 +426,7 @@ export default class Padavan {
|
|
|
409
426
|
|
|
410
427
|
/**
|
|
411
428
|
* Анализирует эфир и предлагает лучший канал с учетом совместимости и региона.
|
|
412
|
-
* @param {
|
|
429
|
+
* @param {WifiBand} [band='2.4'] Частотный диапазон.
|
|
413
430
|
* @param {WifiNetwork[]} [scanResults] Опционально: результаты сканирования.
|
|
414
431
|
* @returns {Promise<ChannelAnalysis>} Результат анализа.
|
|
415
432
|
*/
|
|
@@ -561,7 +578,7 @@ export default class Padavan {
|
|
|
561
578
|
this.log('warn', 'Rebooting router via HTTP...');
|
|
562
579
|
try {
|
|
563
580
|
await this.#http.post(PAGES.APPLY, {
|
|
564
|
-
action_mode:
|
|
581
|
+
action_mode: SYSTEM_ACTION.REBOOT
|
|
565
582
|
});
|
|
566
583
|
} catch (e) {
|
|
567
584
|
this.log('debug', 'Reboot request sent (network error expected)', e.message);
|