From fa7be880a7fa1c9dd17cc1e02bc5a1125b71f17b Mon Sep 17 00:00:00 2001 From: Vladislav Ostapov Date: Tue, 16 Sep 2025 18:52:16 +0300 Subject: [PATCH] =?UTF-8?q?front=5Fgenerator:=20=D0=BD=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BE=D1=82=D1=81=D1=82?= =?UTF-8?q?=D1=83=D0=BF=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D1=81=D0=B5?= =?UTF-8?q?=D1=85=20=D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?=D1=85=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2,=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20=D1=81=20=D0=BB=D0=BE?= =?UTF-8?q?=D0=B3=D0=B0=D0=BC=D0=B8=20=D0=B4=D0=BB=D1=8F=20TDMA-=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D0=BC=D0=B8=D0=BD=D0=B0=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front-generator/render-params.json | 3 +- .../template/common/admin-methods.js.j2 | 405 ++++++++--------- front-generator/template/common/admin.html.j2 | 101 ++--- .../template/common/all-params-data.js.j2 | 10 +- .../template/common/all-params-methods.js.j2 | 52 +-- .../template/common/logs-data.js.j2 | 7 + .../template/common/logs-methods.js.j2 | 12 + front-generator/template/common/logs.html.j2 | 17 + .../template/common/monitoring-data.js.j2 | 90 ++-- .../template/common/monitoring-methods.js.j2 | 204 ++++----- .../template/common/monitoring.html.j2 | 205 +++++---- .../template/common/qos-data.js.j2 | 17 +- .../template/common/qos-methods.js.j2 | 424 +++++++++--------- front-generator/template/common/qos.html.j2 | 200 ++++----- .../template/common/setup-methods.js.j2 | 62 +-- front-generator/template/common/setup.html.j2 | 14 +- front-generator/template/main.html | 35 +- src/api-driver/stricts-enable.h | 4 + static/main-scpc.html | 12 +- static/main-shps.html | 5 +- static/main-tdma.html | 57 ++- 21 files changed, 1013 insertions(+), 923 deletions(-) create mode 100644 front-generator/template/common/logs-data.js.j2 create mode 100644 front-generator/template/common/logs-methods.js.j2 create mode 100644 front-generator/template/common/logs.html.j2 diff --git a/front-generator/render-params.json b/front-generator/render-params.json index 40ce5a8..4a260a9 100644 --- a/front-generator/render-params.json +++ b/front-generator/render-params.json @@ -133,7 +133,8 @@ "tabs": [ {"name": "monitoring", "desc": "Мониторинг"}, {"name": "setup", "desc": "Настройки"}, - {"name": "admin", "desc": "Администрирование"} + {"name": "admin", "desc": "Администрирование"}, + {"name": "logs", "desc": "Журнал"} ] }, "scpc": { diff --git a/front-generator/template/common/admin-methods.js.j2 b/front-generator/template/common/admin-methods.js.j2 index a54ff3d..b085236 100644 --- a/front-generator/template/common/admin-methods.js.j2 +++ b/front-generator/template/common/admin-methods.js.j2 @@ -1,217 +1,218 @@ - async settingsUploadUpdate() { - if (!this.uploadFw.filename) { - alert('Выберите файл для загрузки'); - return; - } +async settingsUploadUpdate() { + if (!this.uploadFw.filename) { + alert('Выберите файл для загрузки'); + return; + } - async function readFileAsArrayBuffer(fileName) { - return new Promise((resolve, reject) => { - if (!fileName) { reject(`Файл не выбран`); return } - const reader = new FileReader(); - reader.onload = (e) => { resolve(reader.result) } - reader.onerror = (e) => { reject(e) } - reader.readAsArrayBuffer(fileName) - }) - } + async function readFileAsArrayBuffer(fileName) { + return new Promise((resolve, reject) => { + if (!fileName) { reject(`Файл не выбран`); return } + const reader = new FileReader(); + reader.onload = (e) => { resolve(reader.result) } + reader.onerror = (e) => { reject(e) } + reader.readAsArrayBuffer(fileName) + }) + } + try { + this.submitStatus.firmwareUpload = true + this.uploadFw.progress = 0 + const blob = await readFileAsArrayBuffer(this.uploadFw.filename) + + const xhr = new XMLHttpRequest(); + await new Promise((resolve) => { + xhr.upload.addEventListener("progress", (event) => { + if (event.lengthComputable) { + this.uploadFw.progress = Math.round((event.loaded / event.total) * 1000) / 10; + } + }); + xhr.addEventListener("loadend", () => { + this.uploadFw.progress = 100 + const rep = JSON.parse(xhr.responseText); + this.uploadFw.sha256 = rep['sha256'] + resolve(xhr.readyState === 4 && xhr.status === 200); + }); + xhr.open("PUT", "/api/firmwareUpdate", true); + xhr.setRequestHeader("Content-Type", "application/octet-stream"); + xhr.send(blob); + }); + } catch (e) { + alert(`Ошибка загрузки файла: ${e}`); + } + this.submitStatus.firmwareUpload = false +}, + +async settingsPerformFirmwareUpgrade() { + if (this.submitStatus.firmwareUpgrade) { return } + this.submitStatus.firmwareUpgrade = true + try { + await fetch('/api/doFirmwareUpgrade', { method: 'POST' }) + } catch (e) { + console.log("failed to perform upgrade firmware: ", e) + } + this.submitStatus.firmwareUpgrade = false +}, +{% if modem == 'tdma' %} +async settingsPerformFirmwareUpgradeOta() { + if (this.submitStatus.firmwareUpgradeOta) { return } + this.submitStatus.firmwareUpgradeOta = true + try { + await fetch('/api/doFirmwareUpgrade?ota=1', { method: 'POST' }) + } catch (e) { + console.log("failed to perform upgrade firmware: ", e) + } + this.submitStatus.firmwareUpgradeOta = false +}, +async settingsPerformSetCesPassword() { + if (this.submitStatus.cesPassword) { return } + this.submitStatus.cesPassword = true + try { + await fetch('/api/set/cesPassword', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({'password': this.cesPasswordValue}) + }) + } catch (e) { + console.log("failed to perform set CES password: ", e) + } + this.submitStatus.cesPassword = false +}, +{% endif %} + +doModemReboot() { + if (this.submitStatus.modemReboot !== null) { + return + } + this.submitStatus.modemReboot = 30 + fetch('/api/reboot', { method: 'POST' }).then((r) => {}) +}, +async restoreAllSettings() { + // Порядок применения настроек + const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network']; + + // 1. Чтение JSON-файла, выбранного пользователем + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.accept = '.json'; + + const filePromise = new Promise((resolve, reject) => { + fileInput.onchange = e => { + const file = e.target.files[0]; + if (!file) { + reject(new Error('Файл не выбран')); + return; + } + + const reader = new FileReader(); + reader.onload = event => { try { - this.submitStatus.firmwareUpload = true - this.uploadFw.progress = 0 - const blob = await readFileAsArrayBuffer(this.uploadFw.filename) - - const xhr = new XMLHttpRequest(); - await new Promise((resolve) => { - xhr.upload.addEventListener("progress", (event) => { - if (event.lengthComputable) { - this.uploadFw.progress = Math.round((event.loaded / event.total) * 1000) / 10; - } - }); - xhr.addEventListener("loadend", () => { - this.uploadFw.progress = 100 - const rep = JSON.parse(xhr.responseText); - this.uploadFw.sha256 = rep['sha256'] - resolve(xhr.readyState === 4 && xhr.status === 200); - }); - xhr.open("PUT", "/api/firmwareUpdate", true); - xhr.setRequestHeader("Content-Type", "application/octet-stream"); - xhr.send(blob); - }); - } catch (e) { - alert(`Ошибка загрузки файла: ${e}`); + const jsonData = JSON.parse(event.target.result); + resolve(jsonData); + } catch (error) { + reject(new Error('Ошибка парсинга JSON')); } - this.submitStatus.firmwareUpload = false - }, + }; + reader.onerror = () => reject(new Error('Ошибка чтения файла')); + reader.readAsText(file); + }; + fileInput.click(); + }); - async settingsPerformFirmwareUpgrade() { - if (this.submitStatus.firmwareUpgrade) { return } - this.submitStatus.firmwareUpgrade = true - try { - await fetch('/api/doFirmwareUpgrade', { method: 'POST' }) - } catch (e) { - console.log("failed to perform upgrade firmware: ", e) - } - this.submitStatus.firmwareUpgrade = false - }, - {% if modem == 'tdma' %} - async settingsPerformFirmwareUpgradeOta() { - if (this.submitStatus.firmwareUpgradeOta) { return } - this.submitStatus.firmwareUpgradeOta = true - try { - await fetch('/api/doFirmwareUpgrade?ota=1', { method: 'POST' }) - } catch (e) { - console.log("failed to perform upgrade firmware: ", e) - } - this.submitStatus.firmwareUpgradeOta = false - }, - async settingsPerformSetCesPassword() { - if (this.submitStatus.cesPassword) { return } - this.submitStatus.cesPassword = true - try { - await fetch('/api/set/cesPassword', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({'password': this.cesPasswordValue}) - }) - } catch (e) { - console.log("failed to perform set CES password: ", e) - } - this.submitStatus.cesPassword = false - }, - {% endif %} + try { + const settingsToApply = await filePromise; + const errors = []; - doModemReboot() { - if (this.submitStatus.modemReboot !== null) { - return - } - this.submitStatus.modemReboot = 30 - fetch('/api/reboot', { method: 'POST' }).then((r) => {}) - }, - async restoreAllSettings() { - // Порядок применения настроек - const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network']; + // 2. Перебор групп параметров в заданном порядке + for (const groupName of settingsApplyOrder) { + if (!settingsToApply.hasOwnProperty(groupName)) { + continue; // Пропускаем группы, которых нет в файле + } - // 1. Чтение JSON-файла, выбранного пользователем - const fileInput = document.createElement('input'); - fileInput.type = 'file'; - fileInput.accept = '.json'; + const groupSettings = settingsToApply[groupName]; + if (typeof groupSettings !== 'object' || groupSettings === null) { + continue; + } - const filePromise = new Promise((resolve, reject) => { - fileInput.onchange = e => { - const file = e.target.files[0]; - if (!file) { - reject(new Error('Файл не выбран')); - return; - } - - const reader = new FileReader(); - reader.onload = event => { - try { - const jsonData = JSON.parse(event.target.result); - resolve(jsonData); - } catch (error) { - reject(new Error('Ошибка парсинга JSON')); - } - }; - reader.onerror = () => reject(new Error('Ошибка чтения файла')); - reader.readAsText(file); - }; - fileInput.click(); + try { + // 2.1. POST-запрос для применения группы параметров + const postResponse = await fetch(`/api/set/${groupName}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(groupSettings) }); - try { - const settingsToApply = await filePromise; - const errors = []; - - // 2. Перебор групп параметров в заданном порядке - for (const groupName of settingsApplyOrder) { - if (!settingsToApply.hasOwnProperty(groupName)) { - continue; // Пропускаем группы, которых нет в файле - } - - const groupSettings = settingsToApply[groupName]; - if (typeof groupSettings !== 'object' || groupSettings === null) { - continue; - } - - try { - // 2.1. POST-запрос для применения группы параметров - const postResponse = await fetch(`/api/set/${groupName}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(groupSettings) - }); - - if (!postResponse.ok) { - throw new Error(`HTTP error ${postResponse.status}`); - } - - const postResult = await postResponse.json(); - if (postResult.status !== 'ok') { - throw new Error(`API error: ${postResult.message || 'unknown error'}`); - } - - // 2.2. Проверка примененных параметров - const getResponse = await fetch('/api/get/settings', { method: 'GET' }); - if (!getResponse.ok) { - throw new Error(`HTTP error ${getResponse.status}`); - } - - const fetchSettingsResult = await getResponse.json(); - if (fetchSettingsResult.status !== 'ok') { - throw new Error('Не удалось получить текущие настройки'); - } - - // Проверка соответствия параметров - const appliedGroup = fetchSettingsResult.settings[groupName] || {}; - const failedSettings = []; - - for (const [key, value] of Object.entries(groupSettings)) { - if (appliedGroup[key] !== value) { - failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`); - } - } - - if (failedSettings.length > 0) { - throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`); - } - - } catch (groupError) { - errors.push(`Группа ${groupName}: ${groupError.message}`); - } - } - - // 3. Показ ошибок, если они есть - if (errors.length > 0) { - const errorMessage = errors.join('\n\n') + - '\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.'; - alert(errorMessage); - } - - } catch (error) { - alert(`Ошибка при восстановлении настроек: ${error.message}`); - return; + if (!postResponse.ok) { + throw new Error(`HTTP error ${postResponse.status}`); } - // 4. Перезагрузка страницы - location.reload(); - }, - async dumpAllSettings() { - function downloadAsFile(data, filename) { - let a = document.createElement("a"); - let file = new Blob([data], {type: 'application/json'}); - a.href = URL.createObjectURL(file); - a.download = filename; - a.click(); + const postResult = await postResponse.json(); + if (postResult.status !== 'ok') { + throw new Error(`API error: ${postResult.message || 'unknown error'}`); } - const response = await fetch('/api/get/settings', { method: 'GET' }) - if (response.ok) { - const jres = await response.json() - if (jres["status"] === "ok") { - downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json") + + // 2.2. Проверка примененных параметров + const getResponse = await fetch('/api/get/settings', { method: 'GET' }); + if (!getResponse.ok) { + throw new Error(`HTTP error ${getResponse.status}`); + } + + const fetchSettingsResult = await getResponse.json(); + if (fetchSettingsResult.status !== 'ok') { + throw new Error('Не удалось получить текущие настройки'); + } + + // Проверка соответствия параметров + const appliedGroup = fetchSettingsResult.settings[groupName] || {}; + const failedSettings = []; + + for (const [key, value] of Object.entries(groupSettings)) { + if (appliedGroup[key] !== value) { + failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`); } } - }, + + if (failedSettings.length > 0) { + throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`); + } + + } catch (groupError) { + errors.push(`Группа ${groupName}: ${groupError.message}`); + } + } + + // 3. Показ ошибок, если они есть + if (errors.length > 0) { + const errorMessage = errors.join('\n\n') + + '\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.'; + alert(errorMessage); + } + + } catch (error) { + alert(`Ошибка при восстановлении настроек: ${error.message}`); + return; + } + + // 4. Перезагрузка страницы + location.reload(); +}, +async dumpAllSettings() { + function downloadAsFile(data, filename) { + let a = document.createElement("a"); + let file = new Blob([data], {type: 'application/json'}); + a.href = URL.createObjectURL(file); + a.download = filename; + a.click(); + } + const response = await fetch('/api/get/settings', { method: 'GET' }) + if (response.ok) { + const jres = await response.json() + if (jres["status"] === "ok") { + downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json") + } + } +}, + diff --git a/front-generator/template/common/admin.html.j2 b/front-generator/template/common/admin.html.j2 index a5eafff..9505230 100644 --- a/front-generator/template/common/admin.html.j2 +++ b/front-generator/template/common/admin.html.j2 @@ -1,52 +1,53 @@ {% from 'common/widgets.j2' import build_widget %} -
- {% if 'network' in params %} - {% for w in params['network'] %}{{ build_widget('network', w) | indent(12, true) }}{% endfor %} - {% endif %} - {% raw %} -

Система

-
- - - - - - - - -
Версия ПО{{ about.firmwareVersion }}
ID модема{{ about.modemUid }}
Серийный номер{{ about.modemSn }}
MAC интерфейса управления{{ about.macManagement }}
MAC интерфейса данных{{ about.macData }}
-
- -
-
- -
- - -
{% endraw %}{% if modem == 'tdma' %} - -

Вход в сеть ЦЗС

-
- - -
{% endif %}{% raw %} - -

Обновление ПО

-
-

Ручное обновление

- - - - {% endraw %}{% if modem == 'tdma' %} -

Обновление "по воздуху"

- - {% endif %} -
+
+ {% if 'network' in params %} + {% for w in params['network'] %}{{ build_widget('network', w) | indent(4, true) }}{% endfor %} + {% endif %} + {% raw %} +

Система

+
+ + + + + + + + +
Версия ПО{{ about.firmwareVersion }}
ID модема{{ about.modemUid }}
Серийный номер{{ about.modemSn }}
MAC интерфейса управления{{ about.macManagement }}
MAC интерфейса данных{{ about.macData }}
+
+
+
+ +
+ + +
{% endraw %}{% if modem == 'tdma' %} + +

Вход в сеть ЦЗС

+
+ + +
{% endif %}{% raw %} + +

Обновление ПО

+
+

Ручное обновление

+ + + + {% endraw %}{% if modem == 'tdma' %} +

Обновление "по воздуху"

+ + {% endif %} +
+
+ diff --git a/front-generator/template/common/all-params-data.js.j2 b/front-generator/template/common/all-params-data.js.j2 index 02445a9..153f37d 100644 --- a/front-generator/template/common/all-params-data.js.j2 +++ b/front-generator/template/common/all-params-data.js.j2 @@ -1,7 +1,7 @@ {% for g in paramGroups %} - param{{ g['group'] | title }}: { - {% for p in g['params'] %} - {{ p['name'] }}: {{ p['initValue'] }}, - {% endfor %} - }, +param{{ g['group'] | title }}: { + {% for p in g['params'] %} + {{ p['name'] }}: {{ p['initValue'] }}, + {% endfor %} +}, {% endfor %} \ No newline at end of file diff --git a/front-generator/template/common/all-params-methods.js.j2 b/front-generator/template/common/all-params-methods.js.j2 index 48d47f1..296e052 100644 --- a/front-generator/template/common/all-params-methods.js.j2 +++ b/front-generator/template/common/all-params-methods.js.j2 @@ -1,30 +1,30 @@ {% from 'common/widgets.j2' import build_getter_js, build_setter_js %} - {% for g in paramGroups %} - settingsSubmit{{ g['group'] | title }}() { - if (this.submitStatus.{{ g['group'] }}) { return } - {% if g['group'] in dangerousParamGroups %} - { if (!confirm("{{ dangerousParamGroups[g['group']] }}")) return } - {% endif %} +{% for g in paramGroups %} +settingsSubmit{{ g['group'] | title }}() { + if (this.submitStatus.{{ g['group'] }}) { return } + {% if g['group'] in dangerousParamGroups %} + { if (!confirm("{{ dangerousParamGroups[g['group']] }}")) return } + {% endif %} - let query = { - {% for p in g['params'] %} - "{{ p['name'] }}": {{ build_getter_js(g['group'], p) }}, - {% endfor %} - } + let query = { + {% for p in g['params'] %} + "{{ p['name'] }}": {{ build_getter_js(g['group'], p) }}, + {% endfor %} + } - this.submitStatus.{{ g['group'] }} = true - fetch('/api/set/{{ g["group"] }}', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' }) - .then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.update{{ g['group'] | title }}Settings(vals) }) - .catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) }) - .finally(() => { this.submitStatus.{{ g['group'] }} = false }) - }, - {% endfor %} + this.submitStatus.{{ g['group'] }} = true + fetch('/api/set/{{ g["group"] }}', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' }) + .then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.update{{ g['group'] | title }}Settings(vals) }) + .catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) }) + .finally(() => { this.submitStatus.{{ g['group'] }} = false }) +}, +{% endfor %} - {% for g in paramGroups %} - update{{ g['group'] | title }}Settings(vals) { - this.submitStatus.{{ g['group'] }} = false - {% for p in g['params'] %} - {{ build_setter_js(g['group'], p, "vals[\"settings\"][\"" ~ g['group'] ~ "\"][\"" ~ p['name'] ~ "\"]") }} - {% endfor %} - }, - {% endfor %} \ No newline at end of file +{% for g in paramGroups %} +update{{ g['group'] | title }}Settings(vals) { + this.submitStatus.{{ g['group'] }} = false + {% for p in g['params'] %} + {{ build_setter_js(g['group'], p, "vals[\"settings\"][\"" ~ g['group'] ~ "\"][\"" ~ p['name'] ~ "\"]") }} + {% endfor %} +}, +{% endfor %} \ No newline at end of file diff --git a/front-generator/template/common/logs-data.js.j2 b/front-generator/template/common/logs-data.js.j2 new file mode 100644 index 0000000..4f77ff4 --- /dev/null +++ b/front-generator/template/common/logs-data.js.j2 @@ -0,0 +1,7 @@ +paramLogs: { + submitClearLogs: false, + submitUpdateLogs: false, + data: "", + level: "" +}, + diff --git a/front-generator/template/common/logs-methods.js.j2 b/front-generator/template/common/logs-methods.js.j2 new file mode 100644 index 0000000..3ccb510 --- /dev/null +++ b/front-generator/template/common/logs-methods.js.j2 @@ -0,0 +1,12 @@ +logsUpdate() { + if (this.paramLogs.submitUpdateLogs) { return } + this.paramLogs.submitUpdateLogs = true + fetch(`/api/get/manager.log?preview=1`, {method: 'GET', credentials: 'same-origin' }) + .then(async (resp) => { + this.paramLogs.data = await resp.text() + }) + .catch((reason) => { this.paramLogs.data = `Ошибка при чтении логов: ${reason}` }) + .finally(() => { this.paramLogs.submitUpdateLogs = false }) +}, + + diff --git a/front-generator/template/common/logs.html.j2 b/front-generator/template/common/logs.html.j2 new file mode 100644 index 0000000..fade68e --- /dev/null +++ b/front-generator/template/common/logs.html.j2 @@ -0,0 +1,17 @@ +{% from 'common/widgets.j2' import build_widget %} +
+

Журнал manager

+
+{{ build_widget('logs', { + "widget": "select", "label": "Фильтрация лога (отображение)", "name": "level", + "values": [{"label": "Без фильтрации", "value": "''"}, {"label": "Информация", "value": "'info'"}, {"label": "Предупреждение", "value": "'warning'"}, {"label": "Ошибка", "value": "'error'"}, {"label": "Фатальная ошибка", "value": "'fatal'"}] + }) | indent(8, true) }} + + Скачать все +
{{ '{{ paramLogs.data }}' }}
+
+
+
+
+
+
diff --git a/front-generator/template/common/monitoring-data.js.j2 b/front-generator/template/common/monitoring-data.js.j2 index 65a6c48..5431379 100644 --- a/front-generator/template/common/monitoring-data.js.j2 +++ b/front-generator/template/common/monitoring-data.js.j2 @@ -1,50 +1,48 @@ - statRx: { - // индикаторы - state: '?', // общее состояние - sym_sync_lock: '?', // захват символьной - freq_search_lock: '?', // Захват поиска по частоте - afc_lock: '?', // захват ФАПЧ - pkt_sync: '?', // захват пакетной синхронизации +statRx: { + // индикаторы + state: '?', // общее состояние + sym_sync_lock: '?', // захват символьной + freq_search_lock: '?', // Захват поиска по частоте + afc_lock: '?', // захват ФАПЧ + pkt_sync: '?', // захват пакетной синхронизации - // куча других параметров, идет в том же порядке, что и в таблице - snr: '?', rssi: '?', - modcod: '?', frameSizeNormal: '?', - isPilots: '?', - symError: '?', - freqErr: '?', freqErrAcc: '?', - inputSignalLevel: '?', - pllError: '?', - speedOnRxKbit: '?', - speedOnIifKbit: '?', + // куча других параметров, идет в том же порядке, что и в таблице + snr: '?', rssi: '?', + modcod: '?', frameSizeNormal: '?', + isPilots: '?', + symError: '?', + freqErr: '?', freqErrAcc: '?', + inputSignalLevel: '?', + pllError: '?', + speedOnRxKbit: '?', + speedOnIifKbit: '?', - // статистика пакетов - packetsOk: '?', packetsBad: '?', packetsDummy: '?', - }, - statTx: { - // состояние - state: '?', + // статистика пакетов + packetsOk: '?', packetsBad: '?', packetsDummy: '?', +}, +statTx: { + // состояние + state: '?', - // прочие поля - {% if modem == 'scpc' %} - snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?' - {% else %} - modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?' - {% endif %} - }, - {% if modem == 'scpc' %} - statCinc: { - occ: '?', - correlator: null, - correlatorFails: '?', - freqErr: '?', freqErrAcc: '?', - channelDelay: '?' - }, - {% endif %} - statDevice: { // температурные датчики - adrv: 0, zynq: 0, fpga: 0 - {% if modem == 'tdma' %}, - upgradeStatus: "", upgradePercent: 0, upgradeImage: "" - {% endif %} - }, - statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'}, + // прочие поля + {% if modem == 'scpc' %} + snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?' + {% else %} + modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?' + {% endif %} +}, +{% if modem == 'scpc' %} +statCinc: { + occ: '?', + correlator: null, + correlatorFails: '?', + freqErr: '?', freqErrAcc: '?', + channelDelay: '?' +}, +{% endif %} +statDevice: { // температурные датчики + adrv: 0, zynq: 0, fpga: 0{% if modem == 'tdma' %}, upgradeStatus: "", upgradePercent: 0, upgradeImage: ""{% endif %} + +}, +statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'}, diff --git a/front-generator/template/common/monitoring-methods.js.j2 b/front-generator/template/common/monitoring-methods.js.j2 index 24255e3..22d6af5 100644 --- a/front-generator/template/common/monitoring-methods.js.j2 +++ b/front-generator/template/common/monitoring-methods.js.j2 @@ -1,110 +1,110 @@ - updateStatistics(vals) { - function modcodToStr(modcod) { - // модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf - const modcods = [ - "DUMMY", - "QPSK 1/4", "QPSK 1/3", "QPSK 2/5", "QPSK 1/2", "QPSK 3/5", "QPSK 2/3", "QPSK 3/4", "QPSK 4/5", "QPSK 5/6", "QPSK 8/9", "QPSK 9/10", - "8PSK 3/5", "8PSK 2/3", "8PSK 3/4", "8PSK 5/6", "8PSK 8/9", "8PSK 9/10", - "16APSK 2/3", "16APSK 3/4", "16APSK 4/5", "16APSK 5/6", "16APSK 8/9", "16APSK 9/10", - "32APSK 3/4", "32APSK 4/5", "32APSK 5/6", "32APSK 8/9", "32APSK 9/10", - ] - if (typeof modcod != "number") { - return "?"; - } - if (modcod < 0 || modcod >= modcods.length) { - return `? (${modcod})` - } - return modcods[modcod] - } +updateStatistics(vals) { + function modcodToStr(modcod) { + // модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf + const modcods = [ + "DUMMY", + "QPSK 1/4", "QPSK 1/3", "QPSK 2/5", "QPSK 1/2", "QPSK 3/5", "QPSK 2/3", "QPSK 3/4", "QPSK 4/5", "QPSK 5/6", "QPSK 8/9", "QPSK 9/10", + "8PSK 3/5", "8PSK 2/3", "8PSK 3/4", "8PSK 5/6", "8PSK 8/9", "8PSK 9/10", + "16APSK 2/3", "16APSK 3/4", "16APSK 4/5", "16APSK 5/6", "16APSK 8/9", "16APSK 9/10", + "32APSK 3/4", "32APSK 4/5", "32APSK 5/6", "32APSK 8/9", "32APSK 9/10", + ] + if (typeof modcod != "number") { + return "?"; + } + if (modcod < 0 || modcod >= modcods.length) { + return `? (${modcod})` + } + return modcods[modcod] + } - this.lastUpdateTime = new Date(); - this.initState = vals["state"]["initState"] - this.testState = vals["state"]["testState"] - {% if modem == 'scpc' %} - this.isCinC = vals["state"]["isCinC"] - {% endif %} + this.lastUpdateTime = new Date(); + this.initState = vals["state"]["initState"] + this.testState = vals["state"]["testState"] + {% if modem == 'scpc' %} + this.isCinC = vals["state"]["isCinC"] + {% endif %} - this.statRx.state = vals["state"]["rx"]["state"] - this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"] - this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"] - this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"] - this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"] - this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10 - this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10 - this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"]) - this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"] - this.statRx.isPilots = vals["state"]["rx"]["isPilots"] - this.statRx.symError = vals["state"]["rx"]["symError"] - this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100 - this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100 - this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"] - this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100 - this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100 - this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100 - this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"] - this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"] - this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"] + this.statRx.state = vals["state"]["rx"]["state"] + this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"] + this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"] + this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"] + this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"] + this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10 + this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10 + this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"]) + this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"] + this.statRx.isPilots = vals["state"]["rx"]["isPilots"] + this.statRx.symError = vals["state"]["rx"]["symError"] + this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100 + this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100 + this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"] + this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100 + this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100 + this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100 + this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"] + this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"] + this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"] - {% if modem == 'scpc' %} - this.statTx.state = vals["state"]["tx"]["state"] - this.statTx.snr = Math.round(vals["state"]["tx"]["snr"] * 100) / 100 - this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"]) - this.statTx.frameSizeNormal = vals["state"]["tx"]["frameSizeNormal"] - this.statTx.isPilots = vals["state"]["tx"]["isPilots"] - this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100 - this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100 + {% if modem == 'scpc' %} + this.statTx.state = vals["state"]["tx"]["state"] + this.statTx.snr = Math.round(vals["state"]["tx"]["snr"] * 100) / 100 + this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"]) + this.statTx.frameSizeNormal = vals["state"]["tx"]["frameSizeNormal"] + this.statTx.isPilots = vals["state"]["tx"]["isPilots"] + this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100 + this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100 - this.statCinc.occ = vals["state"]["cinc"]["occ"] - this.statCinc.correlator = vals["state"]["cinc"]["correlator"] - this.statCinc.correlatorFails = vals["state"]["cinc"]["correlatorFails"] - this.statCinc.freqErr = Math.round(vals["state"]["cinc"]["freqErr"] * 100) / 100 - this.statCinc.freqErrAcc = Math.round(vals["state"]["cinc"]["freqErrAcc"] * 100) / 100 - this.statCinc.channelDelay = vals["state"]["cinc"]["channelDelay"] - {% else %} - this.statTx.state = vals["state"]["tx"]["state"] - this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"]) - this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100 - this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100 - this.statTx.centerFreq = vals["state"]["tx"]["centerFreq"] - this.statTx.symSpeed = vals["state"]["tx"]["symSpeed"] - {% endif %} + this.statCinc.occ = vals["state"]["cinc"]["occ"] + this.statCinc.correlator = vals["state"]["cinc"]["correlator"] + this.statCinc.correlatorFails = vals["state"]["cinc"]["correlatorFails"] + this.statCinc.freqErr = Math.round(vals["state"]["cinc"]["freqErr"] * 100) / 100 + this.statCinc.freqErrAcc = Math.round(vals["state"]["cinc"]["freqErrAcc"] * 100) / 100 + this.statCinc.channelDelay = vals["state"]["cinc"]["channelDelay"] + {% else %} + this.statTx.state = vals["state"]["tx"]["state"] + this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"]) + this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100 + this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100 + this.statTx.centerFreq = vals["state"]["tx"]["centerFreq"] + this.statTx.symSpeed = vals["state"]["tx"]["symSpeed"] + {% endif %} - this.statDevice.adrv = vals["state"]["device"]["adrv"] - this.statDevice.zynq = vals["state"]["device"]["zynq"] - this.statDevice.fpga = vals["state"]["device"]["fpga"] - {% if modem == 'tdma' %} - this.statDevice.upgradeStatus = vals["state"]["device"]["upgradeStatus"] - this.statDevice.upgradePercent = vals["state"]["device"]["upgradePercent"] - this.statDevice.upgradeImage = vals["state"]["device"]["upgradeImage"] - {% endif %} + this.statDevice.adrv = vals["state"]["device"]["adrv"] + this.statDevice.zynq = vals["state"]["device"]["zynq"] + this.statDevice.fpga = vals["state"]["device"]["fpga"] + {% if modem == 'tdma' %} + this.statDevice.upgradeStatus = vals["state"]["device"]["upgradeStatus"] + this.statDevice.upgradePercent = vals["state"]["device"]["upgradePercent"] + this.statDevice.upgradeImage = vals["state"]["device"]["upgradeImage"] + {% endif %} - // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид - let uptime = vals["state"]["device"]["uptime"] - if (uptime) { - let secs = uptime % 60; uptime = Math.floor(uptime / 60) - let mins = uptime % 60; uptime = Math.floor(uptime / 60) - let hours = uptime % 24 - uptime = Math.floor( uptime / 24) - let res = `${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}` - if (uptime > 0) { res = `${uptime} дней, ` + res } - this.statOs.uptime = res - } else { - this.statOs.uptime = '?' - } - this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100 - this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100 - this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100 - this.statOs.totalram = vals["state"]["device"]["totalram"] - this.statOs.freeram = vals["state"]["device"]["freeram"] - }, + // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид + let uptime = vals["state"]["device"]["uptime"] + if (uptime) { + let secs = uptime % 60; uptime = Math.floor(uptime / 60) + let mins = uptime % 60; uptime = Math.floor(uptime / 60) + let hours = uptime % 24 + uptime = Math.floor( uptime / 24) + let res = `${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}` + if (uptime > 0) { res = `${uptime} дней, ` + res } + this.statOs.uptime = res + } else { + this.statOs.uptime = '?' + } + this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100 + this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100 + this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100 + this.statOs.totalram = vals["state"]["device"]["totalram"] + this.statOs.freeram = vals["state"]["device"]["freeram"] +}, - resetPacketsStatistics() { - fetch('/api/resetPacketStatistics', { - method: 'POST', credentials: 'same-origin' - }).then(() => { - this.statRx.packetsOk = 0 - this.statRx.packetsBad = 0 - this.statRx.packetsDummy = 0 - }) - }, +resetPacketsStatistics() { + fetch('/api/resetPacketStatistics', { + method: 'POST', credentials: 'same-origin' + }).then(() => { + this.statRx.packetsOk = 0 + this.statRx.packetsBad = 0 + this.statRx.packetsDummy = 0 + }) +}, diff --git a/front-generator/template/common/monitoring.html.j2 b/front-generator/template/common/monitoring.html.j2 index 2f6e927..09f4854 100644 --- a/front-generator/template/common/monitoring.html.j2 +++ b/front-generator/template/common/monitoring.html.j2 @@ -1,103 +1,102 @@ - {% raw %} -
-
-

Статистика приема

- - {% endraw %}{% if modem != 'shps' %}{% raw %} - - - - - - - - - - - - - - - - - - - {% endraw %}{% else %}{% raw %} - - - - - - - - - - {% endraw %}{% endif %}{% raw %} - -
Прием
Захват символьной
Захват ФАПЧ
Захват поиска по частоте
Захват пакетной синхр.
ОСШ/RSSI{{ statRx.snr }} / {{ statRx.rssi }}
Modcod{{ statRx.modcod }}
Размер кадра{{ statRx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statRx.isPilots ? 'pilots' : 'no pilots' }}
Символьная ошибка{{ statRx.symError }}
Грубая/точная част. ошибка, Гц{{ statRx.freqErr }} / {{ statRx.freqErrAcc }}
Ур. входного сигнала{{ statRx.inputSignalLevel }}
Ошибка ФАПЧ{{ statRx.pllError }}
Инф. скорость на приеме{{ statRx.speedOnRxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statRx.speedOnIifKbit }} кбит/с
Статистика пакетов
Качественных пакетов{{ statRx.packetsOk }}
Поврежденных пакетов{{ statRx.packetsBad }}
DUMMY{{ statRx.packetsDummy }}
Прием
ОСШ/RSSI{{ statRx.snr }} / {{ statRx.rssi }}
Частотная ошибка, Гц{{ statRx.freqErrAcc }}
Ур. входного сигнала{{ statRx.inputSignalLevel }}
Ошибка ФАПЧ{{ statRx.pllError }}
Инф. скорость на приеме{{ statRx.speedOnRxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statRx.speedOnIifKbit }} кбит/с
Статистика пакетов
Качественных пакетов{{ statRx.packetsOk }}
Поврежденных пакетов{{ statRx.packetsBad }}
- -
-
-

Статистика передачи

{% endraw %}{% if modem == 'scpc' %}{% raw %} - - - - - - - - - - -
Передача
ОСШ дальнего приема{{ statTx.snr }}
Modcod{{ statTx.modcod }}
Размер кадра{{ statTx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statTx.isPilots ? 'pilots' : 'no pilots' }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
{% endraw %}{% elif modem == 'tdma' %}{% raw %} - - - - - - - - - -
Передача
Modcod{{ statTx.modcod }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
Центральная частота{{ statTx.centerFreq }} кГц
Символьная скорость{{ statTx.symSpeed }} ksymb
{% endraw %}{% elif modem == 'shps' %}{% raw %} - - - - - - - - -
Передача
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
Центральная частота{{ statTx.centerFreq }} кГц
Символьная скорость{{ statTx.symSpeed }} ksymb
{% endraw %}{% endif %}{% raw %} -
{% endraw %}{% if modem == 'scpc' %}{% raw %} -
-

Статистика режима CinC

- - - - - - - - -
ОСС{{ statCinc.occ }}
Захват коррелятора
Кол-во срывов коррелятора{{ statCinc.correlatorFails }}
Грубая/точная част. ошибка, Гц{{ statCinc.freqErr }} / {{ statCinc.freqErrAcc }}
Задержка в канале, мс{{ statCinc.channelDelay }}
-
{% endraw %}{% endif %}{% raw %} -
-

Состояние устройства

- - - - - - - - {% endraw %}{% if modem == 'tdma' %}{% raw %} - - - - {% endraw %}{% endif %}{% raw %} - -
Температура ADRV{{ statDevice.adrv }} °C
Температура ZYNQ{{ statDevice.zynq }} °C
Температура FPGA{{ statDevice.fpga }} °C
Время работы устройства{{ statOs.uptime }}
Средняя загрузка ЦП (1/5/15 мин.){{ statOs.load1 }}% {{ statOs.load5 }}% {{ statOs.load15 }}%
ОЗУ всего/свободно{{ statOs.totalram }}МБ/{{ statOs.freeram }}МБ
Статус обновления
Статус{{ statDevice.upgradeStatus }}
Прогресс{{ statDevice.upgradePercent }}%
Имя образа{{ statDevice.upgradeImage }}
-
-
- {% endraw %} \ No newline at end of file +{% raw %}
+
+

Статистика приема

+ + {% endraw %}{% if modem != 'shps' %}{% raw %} + + + + + + + + + + + + + + + + + + + {% endraw %}{% else %}{% raw %} + + + + + + + + + + {% endraw %}{% endif %}{% raw %} + +
Прием
Захват символьной
Захват ФАПЧ
Захват поиска по частоте
Захват пакетной синхр.
ОСШ/RSSI{{ statRx.snr }} / {{ statRx.rssi }}
Modcod{{ statRx.modcod }}
Размер кадра{{ statRx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statRx.isPilots ? 'pilots' : 'no pilots' }}
Символьная ошибка{{ statRx.symError }}
Грубая/точная част. ошибка, Гц{{ statRx.freqErr }} / {{ statRx.freqErrAcc }}
Ур. входного сигнала{{ statRx.inputSignalLevel }}
Ошибка ФАПЧ{{ statRx.pllError }}
Инф. скорость на приеме{{ statRx.speedOnRxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statRx.speedOnIifKbit }} кбит/с
Статистика пакетов
Качественных пакетов{{ statRx.packetsOk }}
Поврежденных пакетов{{ statRx.packetsBad }}
DUMMY{{ statRx.packetsDummy }}
Прием
ОСШ/RSSI{{ statRx.snr }} / {{ statRx.rssi }}
Частотная ошибка, Гц{{ statRx.freqErrAcc }}
Ур. входного сигнала{{ statRx.inputSignalLevel }}
Ошибка ФАПЧ{{ statRx.pllError }}
Инф. скорость на приеме{{ statRx.speedOnRxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statRx.speedOnIifKbit }} кбит/с
Статистика пакетов
Качественных пакетов{{ statRx.packetsOk }}
Поврежденных пакетов{{ statRx.packetsBad }}
+ +
+
+

Статистика передачи

{% endraw %}{% if modem == 'scpc' %}{% raw %} + + + + + + + + + + +
Передача
ОСШ дальнего приема{{ statTx.snr }}
Modcod{{ statTx.modcod }}
Размер кадра{{ statTx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statTx.isPilots ? 'pilots' : 'no pilots' }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
{% endraw %}{% elif modem == 'tdma' %}{% raw %} + + + + + + + + + +
Передача
Modcod{{ statTx.modcod }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
Центральная частота{{ statTx.centerFreq }} кГц
Символьная скорость{{ statTx.symSpeed }} ksymb
{% endraw %}{% elif modem == 'shps' %}{% raw %} + + + + + + + + +
Передача
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} кбит/с
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} кбит/с
Центральная частота{{ statTx.centerFreq }} кГц
Символьная скорость{{ statTx.symSpeed }} ksymb
{% endraw %}{% endif %}{% raw %} +
{% endraw %}{% if modem == 'scpc' %}{% raw %} +
+

Статистика режима CinC

+ + + + + + + + +
ОСС{{ statCinc.occ }}
Захват коррелятора
Кол-во срывов коррелятора{{ statCinc.correlatorFails }}
Грубая/точная част. ошибка, Гц{{ statCinc.freqErr }} / {{ statCinc.freqErrAcc }}
Задержка в канале, мс{{ statCinc.channelDelay }}
+
{% endraw %}{% endif %}{% raw %} +
+

Состояние устройства

+ + + + + + + + {% endraw %}{% if modem == 'tdma' %}{% raw %} + + + + {% endraw %}{% endif %}{% raw %} + +
Температура ADRV{{ statDevice.adrv }} °C
Температура ZYNQ{{ statDevice.zynq }} °C
Температура FPGA{{ statDevice.fpga }} °C
Время работы устройства{{ statOs.uptime }}
Средняя загрузка ЦП (1/5/15 мин.){{ statOs.load1 }}% {{ statOs.load5 }}% {{ statOs.load15 }}%
ОЗУ всего/свободно{{ statOs.totalram }}МБ/{{ statOs.freeram }}МБ
Статус обновления
Статус{{ statDevice.upgradeStatus }}
Прогресс{{ statDevice.upgradePercent }}%
Имя образа{{ statDevice.upgradeImage }}
+
+
+{% endraw %} \ No newline at end of file diff --git a/front-generator/template/common/qos-data.js.j2 b/front-generator/template/common/qos-data.js.j2 index 31da867..6b3935a 100644 --- a/front-generator/template/common/qos-data.js.j2 +++ b/front-generator/template/common/qos-data.js.j2 @@ -1,8 +1,9 @@ - submitStatusQos: false, - paramQos: { - en: false, - rt1: [], - rt2: [], - rt3: [], - cd: [], - }, +submitStatusQos: false, +paramQos: { + en: false, + rt1: [], + rt2: [], + rt3: [], + cd: [], +}, + diff --git a/front-generator/template/common/qos-methods.js.j2 b/front-generator/template/common/qos-methods.js.j2 index 869f340..2199f35 100644 --- a/front-generator/template/common/qos-methods.js.j2 +++ b/front-generator/template/common/qos-methods.js.j2 @@ -1,224 +1,224 @@ - settingsSubmitQoS() { - if (this.submitStatusQos) { return } - this.submitStatusQos = true - function _translateQosClass(trafficClass, qc) { - let res = { +settingsSubmitQoS() { + if (this.submitStatusQos) { return } + this.submitStatusQos = true + function _translateQosClass(trafficClass, qc) { + let res = { + cir: qc['cir'], + description: qc['description'], + filters: [] + } + if (trafficClass === 'cd') { + res.pir = qc.pir + } + if (!qc.isEnabled) { + res.disabled = true + } + for (const fi in qc.filters) { + let filter = {} + if (qc['filters'][fi].vlan !== "") { filter['vlan'] = qc['filters'][fi].vlan } + if (qc['filters'][fi].proto.length > 0) { + let tmp = ""; + for (let pid = 0; pid < qc['filters'][fi].proto.length; pid++) { + if (pid !== 0) { tmp += ',' } + tmp += qc['filters'][fi].proto[pid] + } + filter['proto'] = tmp + } + if (qc['filters'][fi].sport !== "") { filter['sport'] = qc['filters'][fi].sport } + if (qc['filters'][fi].dport !== "") { filter['dport'] = qc['filters'][fi].dport } + if (qc['filters'][fi].ip_src !== "") { filter['ip_src'] = qc['filters'][fi].ip_src } + if (qc['filters'][fi].ip_dest !== "") { filter['ip_dest'] = qc['filters'][fi].ip_dest } + if (qc['filters'][fi].dscp !== "") { filter['dscp'] = qc['filters'][fi].dscp } + + if (Object.keys(filter).length === 0) { continue } + if (!qc.filters[fi].isEnabled) { filter['disabled'] = true } + + res.filters.push(filter) + } + if (res.filters.length === 0) { + // автоматическое выключение класса, если правил нет + res.disabled = true + } + + return res + } + let query = { + "en": this.paramQos.en, + "profile": { + "rt1": [], + "rt2": [], + "rt3": [], + "cd": [] + } + } + for (let i = 0; i < this.paramQos.rt1.length; i++) { query.profile.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) } + for (let i = 0; i < this.paramQos.rt2.length; i++) { query.profile.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) } + for (let i = 0; i < this.paramQos.rt3.length; i++) { query.profile.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) } + for (let i = 0; i < this.paramQos.cd.length; i++) { query.profile.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) } + + //console.log(query) + fetch('/api/set/qos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query), credentials: 'same-origin' + }).then(async (resp) => { + this.submitStatusQos = false + if (resp['error']) { throw new Error(resp['error']) } + this.updateQosSettings(await resp.json()) + }).catch((reason) => { + this.submitStatusQos = false + alert(`Ошибка при применении настроек: ${reason}`) + }) +}, + +updateQosSettings(vals) { + this.submitStatusQos = false + this.paramQos.en = vals["settings"]["qos"]["en"] + + const qosProfile = vals["settings"]["qos"]["profile"] + if (qosProfile !== null && qosProfile !== undefined) { + this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length) + this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length) + this.paramQos.rt3 = [] // .splice(0, this.paramQos.rt3.length) + this.paramQos.cd = [] // .splice(0, this.paramQos.cd.length) + + for (let trafficClass in qosProfile) { + if (['rt1', 'rt2', 'rt3', 'cd'].indexOf(trafficClass) < 0) { + continue + } + + if (Array.isArray(qosProfile[trafficClass])) { + for (let i = 0; i < qosProfile[trafficClass].length; i++) { + const qc = qosProfile[trafficClass][i] + let result = { + isEnabled: !qc.hasOwnProperty('disabled'), cir: qc['cir'], + pir: 0, description: qc['description'], filters: [] } if (trafficClass === 'cd') { - res.pir = qc.pir - } - if (!qc.isEnabled) { - res.disabled = true - } - for (const fi in qc.filters) { - let filter = {} - if (qc['filters'][fi].vlan !== "") { filter['vlan'] = qc['filters'][fi].vlan } - if (qc['filters'][fi].proto.length > 0) { - let tmp = ""; - for (let pid = 0; pid < qc['filters'][fi].proto.length; pid++) { - if (pid !== 0) { tmp += ',' } - tmp += qc['filters'][fi].proto[pid] - } - filter['proto'] = tmp - } - if (qc['filters'][fi].sport !== "") { filter['sport'] = qc['filters'][fi].sport } - if (qc['filters'][fi].dport !== "") { filter['dport'] = qc['filters'][fi].dport } - if (qc['filters'][fi].ip_src !== "") { filter['ip_src'] = qc['filters'][fi].ip_src } - if (qc['filters'][fi].ip_dest !== "") { filter['ip_dest'] = qc['filters'][fi].ip_dest } - if (qc['filters'][fi].dscp !== "") { filter['dscp'] = qc['filters'][fi].dscp } - - if (Object.keys(filter).length === 0) { continue } - if (!qc.filters[fi].isEnabled) { filter['disabled'] = true } - - res.filters.push(filter) - } - if (res.filters.length === 0) { - // автоматическое выключение класса, если правил нет - res.disabled = true - } - - return res - } - let query = { - "en": this.paramQos.en, - "profile": { - "rt1": [], - "rt2": [], - "rt3": [], - "cd": [] - } - } - for (let i = 0; i < this.paramQos.rt1.length; i++) { query.profile.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) } - for (let i = 0; i < this.paramQos.rt2.length; i++) { query.profile.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) } - for (let i = 0; i < this.paramQos.rt3.length; i++) { query.profile.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) } - for (let i = 0; i < this.paramQos.cd.length; i++) { query.profile.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) } - - //console.log(query) - fetch('/api/set/qos', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(query), credentials: 'same-origin' - }).then(async (resp) => { - this.submitStatusQos = false - if (resp['error']) { throw new Error(resp['error']) } - this.updateQosSettings(await resp.json()) - }).catch((reason) => { - this.submitStatusQos = false - alert(`Ошибка при применении настроек: ${reason}`) - }) - }, - - updateQosSettings(vals) { - this.submitStatusQos = false - this.paramQos.en = vals["settings"]["qos"]["en"] - - const qosProfile = vals["settings"]["qos"]["profile"] - if (qosProfile !== null && qosProfile !== undefined) { - this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length) - this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length) - this.paramQos.rt3 = [] // .splice(0, this.paramQos.rt3.length) - this.paramQos.cd = [] // .splice(0, this.paramQos.cd.length) - - for (let trafficClass in qosProfile) { - if (['rt1', 'rt2', 'rt3', 'cd'].indexOf(trafficClass) < 0) { - continue - } - - if (Array.isArray(qosProfile[trafficClass])) { - for (let i = 0; i < qosProfile[trafficClass].length; i++) { - const qc = qosProfile[trafficClass][i] - let result = { - isEnabled: !qc.hasOwnProperty('disabled'), - cir: qc['cir'], - pir: 0, - description: qc['description'], - filters: [] - } - if (trafficClass === 'cd') { - if (qc['pir']) { - result.pir = qc['pir'] - } - } - for (let fi = 0; fi < qc['filters'].length; fi++) { - result.filters.push({ - isEnabled: !qc['filters'][fi].hasOwnProperty('disabled'), - vlan: qc['filters'][fi].hasOwnProperty('vlan') ? qc['filters'][fi]['vlan'] : '', - proto: qc['filters'][fi].hasOwnProperty('proto') ? qc['filters'][fi]['proto'].split(',') : [], - sport: qc['filters'][fi].hasOwnProperty('sport') ? qc['filters'][fi]['sport'] : '', - dport: qc['filters'][fi].hasOwnProperty('dport') ? qc['filters'][fi]['dport'] : '', - ip_src: qc['filters'][fi].hasOwnProperty('ip_src') ? qc['filters'][fi]['ip_src'] : '', - ip_dest: qc['filters'][fi].hasOwnProperty('ip_dest') ? qc['filters'][fi]['ip_dest'] : '', - dscp: qc['filters'][fi].hasOwnProperty('dscp') ? qc['filters'][fi]['dscp'] : '' - }) - } - switch (trafficClass) { - case 'rt1': this.paramQos.rt1.push(result); break - case 'rt2': this.paramQos.rt2.push(result); break - case 'rt3': this.paramQos.rt3.push(result); break - case 'cd': this.paramQos.cd.push(result); break - } - } + if (qc['pir']) { + result.pir = qc['pir'] } } - } - }, - - qosAddClass(name) { - let res = { - isEnabled: true, - cir: 0, - pir: 0, - description: "", - filters: [] - } - switch (name) { - case 'rt1': this.paramQos.rt1.push(res); break - case 'rt2': this.paramQos.rt2.push(res); break - case 'rt3': this.paramQos.rt3.push(res); break - case 'cd': this.paramQos.cd.push(res); break - } - }, - - qosClassAddRule(name, index) { - let rule = { - isEnabled: true, - vlan: "", - proto: [], - sport: "", - dport: "", - ip_src: "", - ip_dest: "", - dscp: "" - } - switch (name) { - case 'rt1': this.paramQos.rt1[index].filters.push(rule); break - case 'rt2': this.paramQos.rt2[index].filters.push(rule); break - case 'rt3': this.paramQos.rt3[index].filters.push(rule); break - case 'cd': this.paramQos.cd[index].filters.push(rule); break - } - }, - - qosDelClass(name, index) { - switch (name) { - case 'rt1': this.paramQos.rt1.splice(index, 1); break - case 'rt2': this.paramQos.rt2.splice(index, 1); break - case 'rt3': this.paramQos.rt3.splice(index, 1); break - case 'cd': this.paramQos.cd.splice(index, 1); break - } - }, - - qosDelFilter(name, index, filterIndex) { - switch (name) { - case 'rt1': this.paramQos.rt1[index].filters.splice(filterIndex, 1); break - case 'rt2': this.paramQos.rt2[index].filters.splice(filterIndex, 1); break - case 'rt3': this.paramQos.rt3[index].filters.splice(filterIndex, 1); break - case 'cd': this.paramQos.cd[index].filters.splice(filterIndex, 1); break - } - }, - - qosGenerateRuleDescription(filter) { - // попытка 1: просто отобразить все фильтры - let result = "" - let isFirst = true; - for (const key in filter) { - if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { - continue + for (let fi = 0; fi < qc['filters'].length; fi++) { + result.filters.push({ + isEnabled: !qc['filters'][fi].hasOwnProperty('disabled'), + vlan: qc['filters'][fi].hasOwnProperty('vlan') ? qc['filters'][fi]['vlan'] : '', + proto: qc['filters'][fi].hasOwnProperty('proto') ? qc['filters'][fi]['proto'].split(',') : [], + sport: qc['filters'][fi].hasOwnProperty('sport') ? qc['filters'][fi]['sport'] : '', + dport: qc['filters'][fi].hasOwnProperty('dport') ? qc['filters'][fi]['dport'] : '', + ip_src: qc['filters'][fi].hasOwnProperty('ip_src') ? qc['filters'][fi]['ip_src'] : '', + ip_dest: qc['filters'][fi].hasOwnProperty('ip_dest') ? qc['filters'][fi]['ip_dest'] : '', + dscp: qc['filters'][fi].hasOwnProperty('dscp') ? qc['filters'][fi]['dscp'] : '' + }) } - if (isFirst) { - isFirst = false; - } else { - result += '; ' - } - result += `${key}: ${filter[key]}` - } - if (result === "") { - return "пустой" - } - - const maxResultLen = 60 - - if (result.length > maxResultLen) { - // попытка 2, отобразить что вообще в этом фильтре использовалось - result = "" - isFirst = true; - for (const key in filter) { - if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { - continue - } - if (isFirst) { - isFirst = false; - } else { - result += ', ' - } - result += `${key}` + switch (trafficClass) { + case 'rt1': this.paramQos.rt1.push(result); break + case 'rt2': this.paramQos.rt2.push(result); break + case 'rt3': this.paramQos.rt3.push(result); break + case 'cd': this.paramQos.cd.push(result); break } } + } + } + } +}, - return result - }, +qosAddClass(name) { + let res = { + isEnabled: true, + cir: 0, + pir: 0, + description: "", + filters: [] + } + switch (name) { + case 'rt1': this.paramQos.rt1.push(res); break + case 'rt2': this.paramQos.rt2.push(res); break + case 'rt3': this.paramQos.rt3.push(res); break + case 'cd': this.paramQos.cd.push(res); break + } +}, + +qosClassAddRule(name, index) { + let rule = { + isEnabled: true, + vlan: "", + proto: [], + sport: "", + dport: "", + ip_src: "", + ip_dest: "", + dscp: "" + } + switch (name) { + case 'rt1': this.paramQos.rt1[index].filters.push(rule); break + case 'rt2': this.paramQos.rt2[index].filters.push(rule); break + case 'rt3': this.paramQos.rt3[index].filters.push(rule); break + case 'cd': this.paramQos.cd[index].filters.push(rule); break + } +}, + +qosDelClass(name, index) { + switch (name) { + case 'rt1': this.paramQos.rt1.splice(index, 1); break + case 'rt2': this.paramQos.rt2.splice(index, 1); break + case 'rt3': this.paramQos.rt3.splice(index, 1); break + case 'cd': this.paramQos.cd.splice(index, 1); break + } +}, + +qosDelFilter(name, index, filterIndex) { + switch (name) { + case 'rt1': this.paramQos.rt1[index].filters.splice(filterIndex, 1); break + case 'rt2': this.paramQos.rt2[index].filters.splice(filterIndex, 1); break + case 'rt3': this.paramQos.rt3[index].filters.splice(filterIndex, 1); break + case 'cd': this.paramQos.cd[index].filters.splice(filterIndex, 1); break + } +}, + +qosGenerateRuleDescription(filter) { + // попытка 1: просто отобразить все фильтры + let result = "" + let isFirst = true; + for (const key in filter) { + if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { + continue + } + if (isFirst) { + isFirst = false; + } else { + result += '; ' + } + result += `${key}: ${filter[key]}` + } + if (result === "") { + return "пустой" + } + + const maxResultLen = 60 + + if (result.length > maxResultLen) { + // попытка 2, отобразить что вообще в этом фильтре использовалось + result = "" + isFirst = true; + for (const key in filter) { + if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { + continue + } + if (isFirst) { + isFirst = false; + } else { + result += ', ' + } + result += `${key}` + } + } + + return result +}, diff --git a/front-generator/template/common/qos.html.j2 b/front-generator/template/common/qos.html.j2 index 26ba039..4d441d3 100644 --- a/front-generator/template/common/qos.html.j2 +++ b/front-generator/template/common/qos.html.j2 @@ -1,107 +1,107 @@ {% from 'common/widgets.j2' import build_widget %} {% raw %} -
-

Настройки QoS

-
- -
-
-

Классы {{ classesGroup.toUpperCase() }}

-
- - #{{ index }} CIR={{ qosClass.cir }}кбит, PIR={{ qosClass.pir }}кбит {{ qosClass.description }} - #{{ index }} CBR={{ qosClass.cir }}кбит {{ qosClass.description }} - - +
+

Настройки QoS

+
+ +
+
+

Классы {{ classesGroup.toUpperCase() }}

+
+ + #{{ index }} CIR={{ qosClass.cir }}кбит, PIR={{ qosClass.pir }}кбит {{ qosClass.description }} + #{{ index }} CBR={{ qosClass.cir }}кбит {{ qosClass.description }} + + - - - + +
+ + + -

Фильтры ({{ qosClass.filters.length }})

-
- -
-
- - #{{ filterIndex }} {{ qosGenerateRuleDescription(filter) }} - - - - - - -
- Протокол L3 - - - - - - - - - - -
- - - - - -
- -
- -
-
+

Фильтры ({{ qosClass.filters.length }})

+
+
- +
+ + #{{ filterIndex }} {{ qosGenerateRuleDescription(filter) }} + + + + + + +
+ Протокол L3 + + + + + + + + + + +
+ + + + + +
- {% endraw %}{% if 'tcpaccel' in params %} - {% for w in params['tcpaccel'] %}{{ build_widget('tcpaccel', w) | indent(12, true) }}{% endfor %} - {% endif %} -
\ No newline at end of file +
+ +
+ +
+ + + {% endraw %}{% if 'tcpaccel' in params %} + {% for w in params['tcpaccel'] %}{{ build_widget('tcpaccel', w) | indent(4, true) }}{% endfor %} + {% endif %} +
\ No newline at end of file diff --git a/front-generator/template/common/setup-methods.js.j2 b/front-generator/template/common/setup-methods.js.j2 index c39017f..dbad835 100644 --- a/front-generator/template/common/setup-methods.js.j2 +++ b/front-generator/template/common/setup-methods.js.j2 @@ -1,34 +1,34 @@ {% if 'rxtx' in params and modem == 'scpc' %} - calcRequiredSnr(frameSizeNormal, modulation, speed) { - const snrValues = [ - {fs: true, mod: 'qpsk', speed: '1/4', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '1/3', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '2/5', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '1/2', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '3/5', snr: 3.1}, {fs: true, mod: 'qpsk', speed: '2/3', snr: 3.8}, {fs: true, mod: 'qpsk', speed: '3/4', snr: 4.5}, {fs: true, mod: 'qpsk', speed: '4/5', snr: 5.2}, {fs: true, mod: 'qpsk', speed: '5/6', snr: 5.5}, {fs: true, mod: 'qpsk', speed: '8/9', snr: 6.4}, {fs: true, mod: 'qpsk', speed: '9/10', snr: 6.7}, - {fs: true, mod: '8psk', speed: '3/5', snr: 7.4}, {fs: true, mod: '8psk', speed: '2/3', snr: 8.4}, {fs: true, mod: '8psk', speed: '3/4', snr: 8.7}, {fs: true, mod: '8psk', speed: '5/6', snr: 10}, {fs: true, mod: '8psk', speed: '8/9', snr: 10.9}, {fs: true, mod: '8psk', speed: '9/10', snr: 11.1}, - {fs: true, mod: '16apsk', speed: '2/3', snr: 11.2}, {fs: true, mod: '16apsk', speed: '3/4', snr: 11.3}, {fs: true, mod: '16apsk', speed: '4/5', snr: 12.4}, {fs: true, mod: '16apsk', speed: '5/6', snr: 12.7}, {fs: true, mod: '16apsk', speed: '8/9', snr: 13.1}, {fs: true, mod: '16apsk', speed: '9/10', snr: 13.9}, - {fs: true, mod: '32apsk', speed: '3/4', snr: 14.5}, {fs: true, mod: '32apsk', speed: '4/5', snr: 14.7}, {fs: true, mod: '32apsk', speed: '5/6', snr: 14.9}, {fs: true, mod: '32apsk', speed: '8/9', snr: 16.1}, {fs: true, mod: '32apsk', speed: '9/10', snr: 16.6}, +calcRequiredSnr(frameSizeNormal, modulation, speed) { + const snrValues = [ + {fs: true, mod: 'qpsk', speed: '1/4', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '1/3', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '2/5', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '1/2', snr: 2.6}, {fs: true, mod: 'qpsk', speed: '3/5', snr: 3.1}, {fs: true, mod: 'qpsk', speed: '2/3', snr: 3.8}, {fs: true, mod: 'qpsk', speed: '3/4', snr: 4.5}, {fs: true, mod: 'qpsk', speed: '4/5', snr: 5.2}, {fs: true, mod: 'qpsk', speed: '5/6', snr: 5.5}, {fs: true, mod: 'qpsk', speed: '8/9', snr: 6.4}, {fs: true, mod: 'qpsk', speed: '9/10', snr: 6.7}, + {fs: true, mod: '8psk', speed: '3/5', snr: 7.4}, {fs: true, mod: '8psk', speed: '2/3', snr: 8.4}, {fs: true, mod: '8psk', speed: '3/4', snr: 8.7}, {fs: true, mod: '8psk', speed: '5/6', snr: 10}, {fs: true, mod: '8psk', speed: '8/9', snr: 10.9}, {fs: true, mod: '8psk', speed: '9/10', snr: 11.1}, + {fs: true, mod: '16apsk', speed: '2/3', snr: 11.2}, {fs: true, mod: '16apsk', speed: '3/4', snr: 11.3}, {fs: true, mod: '16apsk', speed: '4/5', snr: 12.4}, {fs: true, mod: '16apsk', speed: '5/6', snr: 12.7}, {fs: true, mod: '16apsk', speed: '8/9', snr: 13.1}, {fs: true, mod: '16apsk', speed: '9/10', snr: 13.9}, + {fs: true, mod: '32apsk', speed: '3/4', snr: 14.5}, {fs: true, mod: '32apsk', speed: '4/5', snr: 14.7}, {fs: true, mod: '32apsk', speed: '5/6', snr: 14.9}, {fs: true, mod: '32apsk', speed: '8/9', snr: 16.1}, {fs: true, mod: '32apsk', speed: '9/10', snr: 16.6}, - {fs: false, mod: 'qpsk', speed: '1/4', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '1/3', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '2/5', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '1/2', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '3/5', snr: 4.6}, {fs: false, mod: 'qpsk', speed: '2/3', snr: 5.1}, {fs: false, mod: 'qpsk', speed: '3/4', snr: 5.3}, {fs: false, mod: 'qpsk', speed: '4/5', snr: 6.8}, {fs: false, mod: 'qpsk', speed: '5/6', snr: 7.8}, {fs: false, mod: 'qpsk', speed: '8/9', snr: 8.5}, - {fs: false, mod: '8psk', speed: '3/5', snr: 9.5}, {fs: false, mod: '8psk', speed: '2/3', snr: 9.9}, {fs: false, mod: '8psk', speed: '3/4', snr: 10.5}, {fs: false, mod: '8psk', speed: '5/6', snr: 11.1}, {fs: false, mod: '8psk', speed: '8/9', snr: 11.3}, - {fs: false, mod: '16apsk', speed: '2/3', snr: 11.6}, {fs: false, mod: '16apsk', speed: '3/4', snr: 11.8}, {fs: false, mod: '16apsk', speed: '4/5', snr: 12}, {fs: false, mod: '16apsk', speed: '5/6', snr: 12.3}, {fs: false, mod: '16apsk', speed: '8/9', snr: 13.4}, - {fs: false, mod: '32apsk', speed: '3/4', snr: 14.1}, {fs: false, mod: '32apsk', speed: '4/5', snr: 14.7}, {fs: false, mod: '32apsk', speed: '5/6', snr: 15.3}, {fs: false, mod: '32apsk', speed: '8/9', snr: 16.5}, - ] - for (let i = 0; i < snrValues.length; i++) { - if (snrValues[i].fs === frameSizeNormal && snrValues[i].mod === modulation && snrValues[i].speed === speed) { return snrValues[i].snr } - } - return '?' - }, - calcInterfaceSpeedKb(baud, modulation, speed, frameSizeNormal) { - const mBaud = parseInt(baud.replace(/[^0-9]/g, '')) - const mMod = Math.max(2, ['', '', 'qpsk', '8psk', '16apsk', '32apsk'].indexOf(modulation)) - const speedVals = {'1/4': 0.25, '1/3': 0.333, '2/5': 0.4, '1/2': 0.5, '3/5': 0.6, '2/3': 0.666, '3/4': 0.75, '4/5': 0.8, '5/6': 0.833, '8/9': 0.888, '9/10': 0.9} - const mSpeed = speed in speedVals ? speedVals[speed] : 1 - const result = (mBaud * mMod * mSpeed) / 1024 - const calcSnr = this.calcRequiredSnr(frameSizeNormal, modulation, speed) - let snr; - if (isNaN(calcSnr)) { snr = `ОСШ=?` } else { snr=`ОСШ=${calcSnr}` } - if (result > 1024) { - return toLocaleStringWithSpaces(result / 1024) + ' Мбит/с; ' + snr - } else { - return toLocaleStringWithSpaces(result) + ' кбит/с; ' + snr - } - }, + {fs: false, mod: 'qpsk', speed: '1/4', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '1/3', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '2/5', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '1/2', snr: 4.1}, {fs: false, mod: 'qpsk', speed: '3/5', snr: 4.6}, {fs: false, mod: 'qpsk', speed: '2/3', snr: 5.1}, {fs: false, mod: 'qpsk', speed: '3/4', snr: 5.3}, {fs: false, mod: 'qpsk', speed: '4/5', snr: 6.8}, {fs: false, mod: 'qpsk', speed: '5/6', snr: 7.8}, {fs: false, mod: 'qpsk', speed: '8/9', snr: 8.5}, + {fs: false, mod: '8psk', speed: '3/5', snr: 9.5}, {fs: false, mod: '8psk', speed: '2/3', snr: 9.9}, {fs: false, mod: '8psk', speed: '3/4', snr: 10.5}, {fs: false, mod: '8psk', speed: '5/6', snr: 11.1}, {fs: false, mod: '8psk', speed: '8/9', snr: 11.3}, + {fs: false, mod: '16apsk', speed: '2/3', snr: 11.6}, {fs: false, mod: '16apsk', speed: '3/4', snr: 11.8}, {fs: false, mod: '16apsk', speed: '4/5', snr: 12}, {fs: false, mod: '16apsk', speed: '5/6', snr: 12.3}, {fs: false, mod: '16apsk', speed: '8/9', snr: 13.4}, + {fs: false, mod: '32apsk', speed: '3/4', snr: 14.1}, {fs: false, mod: '32apsk', speed: '4/5', snr: 14.7}, {fs: false, mod: '32apsk', speed: '5/6', snr: 15.3}, {fs: false, mod: '32apsk', speed: '8/9', snr: 16.5}, + ] + for (let i = 0; i < snrValues.length; i++) { + if (snrValues[i].fs === frameSizeNormal && snrValues[i].mod === modulation && snrValues[i].speed === speed) { return snrValues[i].snr } + } + return '?' +}, +calcInterfaceSpeedKb(baud, modulation, speed, frameSizeNormal) { + const mBaud = parseInt(baud.replace(/[^0-9]/g, '')) + const mMod = Math.max(2, ['', '', 'qpsk', '8psk', '16apsk', '32apsk'].indexOf(modulation)) + const speedVals = {'1/4': 0.25, '1/3': 0.333, '2/5': 0.4, '1/2': 0.5, '3/5': 0.6, '2/3': 0.666, '3/4': 0.75, '4/5': 0.8, '5/6': 0.833, '8/9': 0.888, '9/10': 0.9} + const mSpeed = speed in speedVals ? speedVals[speed] : 1 + const result = (mBaud * mMod * mSpeed) / 1024 + const calcSnr = this.calcRequiredSnr(frameSizeNormal, modulation, speed) + let snr; + if (isNaN(calcSnr)) { snr = `ОСШ=?` } else { snr=`ОСШ=${calcSnr}` } + if (result > 1024) { + return toLocaleStringWithSpaces(result / 1024) + ' Мбит/с; ' + snr + } else { + return toLocaleStringWithSpaces(result) + ' кбит/с; ' + snr + } +}, {% endif %} diff --git a/front-generator/template/common/setup.html.j2 b/front-generator/template/common/setup.html.j2 index 9d79feb..1745dc3 100644 --- a/front-generator/template/common/setup.html.j2 +++ b/front-generator/template/common/setup.html.j2 @@ -1,8 +1,8 @@ {% from 'common/widgets.j2' import build_widget %} -
- {% for cat in ['rxtx', 'dpdi', 'buclnb'] %} - {% if cat in params %} - {% for w in params[cat] %}{{ build_widget(cat, w) | indent(12, true) }}{% endfor %} - {% endif %} - {% endfor %} -
\ No newline at end of file +
+ {% for cat in ['rxtx', 'dpdi', 'buclnb'] %} + {% if cat in params %} + {% for w in params[cat] %}{{ build_widget(cat, w) | indent(4, true) }}{% endfor %} + {% endif %} + {% endfor %} +
\ No newline at end of file diff --git a/front-generator/template/main.html b/front-generator/template/main.html index 40bce1e..5ca3439 100644 --- a/front-generator/template/main.html +++ b/front-generator/template/main.html @@ -1,5 +1,18 @@ +{% macro include_macro(file) %} +// ========== include from '{{ file }}' +{% include file %} +// ========== include end from '{{ file }}' +{% endmacro %} +{% macro include_macro_no_comment(file) %} +{% include file %} +{% endmacro %} +{% macro include_macro_ignore_missing(file) %} +// ========== include from '{{ file }}' +{% include file ignore missing %} +// ========== include end from '{{ file }}' +{% endmacro %} @@ -53,7 +66,7 @@
- {% for tab in header_tabs %}{% include 'common/' ~ tab.name ~ '.html.j2' %}{% endfor %} + {% for tab in header_tabs %}{{ include_macro_no_comment('common/' ~ tab.name ~ '.html.j2') | indent(8, true) }}{% endfor %} {% raw %}

Последнее обновление статистики: {{ lastUpdateTime }}

@@ -108,15 +121,9 @@ cesPasswordValue: '', {% endif %} - // ========== include from 'common/all-params-data.js.j2' - {% include 'common/all-params-data.js.j2' %} - // ========== include end from 'common/all-params-data.js.j2' - +{{ include_macro('common/all-params-data.js.j2') | indent(16, true) }} {% for tab in header_tabs %} - // ========== include from '{{ 'common/' ~ tab.name ~ '-data.js.j2' }}' - {% include 'common/' ~ tab.name ~ '-data.js.j2' ignore missing %} - // ========== include end from '{{ 'common/' ~ tab.name ~ '-data.js.j2' }}' - +{{ include_macro_ignore_missing('common/' ~ tab.name ~ '-data.js.j2') | indent(16, true) }} {% endfor %} uploadFw: { progress: null, @@ -183,15 +190,9 @@ return toLocaleStringWithSpaces(result) }, - // ========== include from 'common/all-params-methods.js.j2' - {% include 'common/all-params-methods.js.j2' %} - // ========== include end from 'common/all-params-methods.js.j2' - +{{ include_macro('common/all-params-methods.js.j2') | indent(12, true) }} {% for tab in header_tabs %} - // ========== include from '{{ 'common/' ~ tab.name ~ '-methods.js.j2' }}' - {% include 'common/' ~ tab.name ~ '-methods.js.j2' ignore missing %} - // ========== include end from '{{ 'common/' ~ tab.name ~ '-methods.js.j2' }}' - +{{ include_macro_ignore_missing('common/' ~ tab.name ~ '-methods.js.j2') | indent(12, true) }} {% endfor %} performUpdateSettings() { diff --git a/src/api-driver/stricts-enable.h b/src/api-driver/stricts-enable.h index 325aa51..0c9bbdf 100644 --- a/src/api-driver/stricts-enable.h +++ b/src/api-driver/stricts-enable.h @@ -26,5 +26,9 @@ #define API_OBJECT_BUCLNB_SETTINGS_ENABLE #endif +#if defined(MODEM_IS_TDMA) +#define API_OBJECT_MANAGER_LOGS_ENABLE +#endif + #endif //API_DRIVER_STRICTS_ENABLE_H diff --git a/static/main-scpc.html b/static/main-scpc.html index b43f079..54adfe2 100644 --- a/static/main-scpc.html +++ b/static/main-scpc.html @@ -52,7 +52,6 @@
-

Статистика приема

@@ -387,7 +386,7 @@
-
+

Настройки QoS

@@ -454,7 +453,7 @@ - + @@ -549,6 +548,7 @@
+

Последнее обновление статистики: {{ lastUpdateTime }}

@@ -710,7 +710,8 @@ rt2: [], rt3: [], cd: [], - }, // ========== include end from 'common/qos-data.js.j2' + }, + // ========== include end from 'common/qos-data.js.j2' // ========== include from 'common/admin-data.js.j2' // ========== include end from 'common/admin-data.js.j2' @@ -1492,7 +1493,8 @@ downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json") } } - }, // ========== include end from 'common/admin-methods.js.j2' + }, + // ========== include end from 'common/admin-methods.js.j2' performUpdateSettings() { diff --git a/static/main-shps.html b/static/main-shps.html index 871cacd..ba2710e 100644 --- a/static/main-shps.html +++ b/static/main-shps.html @@ -51,7 +51,6 @@
-

Статистика приема

@@ -310,6 +309,7 @@
+

Последнее обновление статистики: {{ lastUpdateTime }}

@@ -903,7 +903,8 @@ downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json") } } - }, // ========== include end from 'common/admin-methods.js.j2' + }, + // ========== include end from 'common/admin-methods.js.j2' performUpdateSettings() { diff --git a/static/main-tdma.html b/static/main-tdma.html index 2a0a826..53dd21d 100644 --- a/static/main-tdma.html +++ b/static/main-tdma.html @@ -47,11 +47,11 @@ Мониторинг Настройки Администрирование + Журнал Выход
-

Статистика приема

@@ -297,12 +297,35 @@
+
+

Журнал manager

+
+ + + + Скачать все +
{{ paramLogs.data }}
+
+
+
+
+
+

Последнее обновление статистики: {{ lastUpdateTime }}