diff --git a/index/views.py b/index/views.py index 65447a6..30c608e 100644 --- a/index/views.py +++ b/index/views.py @@ -24,7 +24,8 @@ def view_stats(request): def view_tank_chart(request): # только для тестирования! - res = requests.get(TEST_BASE_FETCH + "?tank_chart", headers={'Authorization': os.getenv("TEST_AUTH")}) + days = request.GET.get('days', '7') + res = requests.get(TEST_BASE_FETCH + "?tank_chart=" + days, headers={'Authorization': os.getenv("TEST_AUTH")}) response = HttpResponse(res.content) response.headers["Content-type"] = response.headers["Content-type"] return response diff --git a/static/css/style.css b/static/css/style.css index 0a26b61..b43ab16 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -2,6 +2,8 @@ body { --text-color: #262626; --text-color2: #3d3d3d; + --text-good: green; + --text-bad: red; --brand-bg: #EDF3FE; --brand-text: #5488F7; @@ -15,6 +17,8 @@ body { body { --text-color: #eee; --text-color2: #bbb; + --text-good: greenyellow; + --text-bad: orangered; --brand-bg: #393E50; --brand-text: #5F93F3; diff --git a/static/js/index-main.js b/static/js/index-main.js index ca12d43..a123f16 100644 --- a/static/js/index-main.js +++ b/static/js/index-main.js @@ -3,11 +3,6 @@ // интервал обновления статуса в миллисекундах const RELOAD_STATS_INTERVAL = 10000 -// интервал обновления графика - 1% показываемого времени (2 недели) -// const RELOAD_CHART_INTERVAL = (3600 * 1000 * 24 * 14) / 100 -// const RELOAD_CHART_INTERVAL = (3600 * 1000 * 24) / 100 -const RELOAD_CHART_INTERVAL = 30000 - const DATETIME_FORMAT = "DD MMM YYYY HH:mm:ss" function unpackBits(num, desc) { @@ -78,42 +73,116 @@ async function makeRequest(url) { return await response.json() } -async function loadAllData() { - return await makeRequest('/fetch/all') -} - async function loadChartData() { - return (await makeRequest('/fetch/tank-chart'))['tank_chart'] + let chartTime = localStorage.getItem("settings-chart-time") + + return (await makeRequest('/fetch/tank-chart?days=' + chartTime))['tank_chart'] } async function loadLastUpdates() { return (await makeRequest('/fetch/stats'))['stats'] } +/** + * Функция, устанавливающая классы CSS 'value-good' и 'value-bad'. + * @param element + * @param good + * @private + */ +function _setIndicatorClass(element, good) { + if (good) { + element.classList.remove("value-bad") + element.classList.add("value-good") + } else { + element.classList.remove("value-good") + element.classList.add("value-bad") + } +} + +const pumpStageDescription = { + 0: "отключен", + 2: "инициализация: установка задвижек в начальное состояние", + 21: "инициализация: закрытие задвижек 23.5 и 23.6", + 31: "инициализация: открытие задвижек 23.5 и 23.6", + 99: "авария", + 100: "ожидание сигнала на перекачку воды", + 102: "запуск: открытие задвижки 23.6", + 110: "запуск: ожидание сигнала от датчика уровня поз.36", + 121: "запуск: открытие задвижек насоса", + 131: "запуск: закрытие задвижки 23.6", + 141: "запуск: пуск ПЧ", + 200: "работает", + 202: "остановка: закрытие задвижек 23.3 и 23.4", + 211: "остановка: ожидание остановки ПЧ", + 221: "остановка: перевод запорной арматуры в исходное состояние", + 231: "остановка: работа компрессора", + 235: "остановка: сброс конденсата клапанами 25.*" +} + +const pumpAlarmRegister = [ + "общая авария", + "реле контроля фаз", + "насос", + "ошибка ПЧ", + "датчик потока", + "датчик уровня воды", + "датчик наличия воды", + "задвижки" +] + +const vfdErrorsDescription = { + 5: "превышение напряжения", + 8: "пониженное напряжение", + 11: "обрыв фазы питания", + 12: "отказ выходной цепи", + 15: "перегрев ПЧ", + 17: "замыкание двигателя на землю", + 19: "двигатель без нагрузки", + 34: "перегрузка по току" +} + async function updateStatus() { let dataset = await loadLastUpdates() + const now = Date.now() / 1000 + // последнее обновление - document.getElementById("tank-last-update").innerHTML = moment(new Date(dataset['tank']['last_update'] * 1000)).format(DATETIME_FORMAT) - document.getElementById("pump-last-update").innerHTML = moment(new Date(dataset['pump']['last_update'] * 1000)).format(DATETIME_FORMAT) + + // сначала резервуар + let tmp = document.getElementById("tank-last-update") + tmp.innerHTML = moment(new Date(dataset['tank']['last_update'] * 1000)).format(DATETIME_FORMAT) + // для резервуара нормально, если обновление было меньше получаса назад + _setIndicatorClass(tmp, now - dataset['tank']['last_update'] < 1800) + + // теперь то же самое, только для насосной + tmp = document.getElementById("pump-last-update") + tmp.innerHTML = moment(new Date(dataset['pump']['last_update'] * 1000)).format(DATETIME_FORMAT) + // для насосной можно допустить последнее обновление 10 минут назад + _setIndicatorClass(tmp, now - dataset['tank']['last_update'] < 600) //

Уровень воды

const last_radar_values = dataset['tank']['last_radar_values'] if (last_radar_values.length === 0) { - document.getElementById("tank-level-dir").innerHTML = "(?)"; + document.getElementById("tank-level-dir").innerHTML = "(?)" } else { - document.getElementById("tank-level-dir").innerHTML = approximateWithTimestamps(last_radar_values) < 0 ? '↘' : '↗'; + document.getElementById("tank-level-dir").innerHTML = approximateWithTimestamps(last_radar_values) < 0 ? '↘' : '↗' } //

Текущий уровень воды: %

- document.getElementById("tank-level-now").innerHTML = dataset['tank']['last_percentage'] + tmp = document.getElementById("tank-level-now") + tmp.innerHTML = dataset['tank']['last_percentage'] + // тут все хорошо если влезаем в установленные рамки +-2% (69-80%) + _setIndicatorClass(tmp, 67 <= dataset['tank']['last_percentage'] <= 82) //

Текущее значение с радара:

document.getElementById("tank-raw-now").innerHTML = dataset['tank']['last_radar'] //

Статус:

const shur_status_bits = ['нужна вода', 'поплавок нижний', 'поплавок верхний', 'поплавок аварийный'] - document.getElementById("tank-status").innerHTML = unpackBits(dataset['tank']['status_reg'], shur_status_bits) + " (" + dataset['tank']['status_reg'] + ")"; + tmp = document.getElementById("tank-status") + tmp.innerHTML = unpackBits(dataset['tank']['status_reg'], shur_status_bits) + " (" + dataset['tank']['status_reg'] + ")" + // тут все хорошо, пока нет аварийного поплавка + _setIndicatorClass(tmp, (dataset['tank']['status_reg'] & 0x8) === 0) //

Частота ПЧ: Гц

document.getElementById("pump-vfd-freq").innerHTML = dataset['pump']['vfd_freq'] @@ -122,39 +191,32 @@ async function updateStatus() { document.getElementById("pump-vfd-curr").innerHTML = dataset['pump']['vfd_curr'] //

Ошибка ПЧ:

- document.getElementById("pump-vfd-error").innerHTML = dataset['pump']['vfd_err'] + tmp = document.getElementById("pump-vfd-error") + if (dataset['pump']['vfd_err'] in vfdErrorsDescription) { + tmp.innerHTML = dataset['pump']['vfd_err'] + " (" + vfdErrorsDescription[dataset['pump']['vfd_err']] + ")" + } else { + tmp.innerHTML = dataset['pump']['vfd_err'] + } + _setIndicatorClass(tmp, dataset['pump']['vfd_err'] === 0) //

Регистр аварий:

- document.getElementById("pump-alarms").innerHTML = dataset['pump']['alarms'] + tmp = document.getElementById("pump-alarms") + if (dataset['pump']['alarms'] === 0) { + tmp.innerHTML = "ok" + } else { + tmp.innerHTML = unpackBits(dataset['pump']['alarms'], pumpAlarmRegister) + " (" + dataset['pump']['alarms'] + ")" + } + _setIndicatorClass(tmp, dataset['pump']['alarms'] === 0) //

Состояние КА:

- document.getElementById("pump-stage").innerHTML = dataset['pump']['pump_stage'] + tmp = document.getElementById("pump-stage") + if (dataset['pump']['pump_stage'] in pumpStageDescription) { + tmp.innerHTML = dataset['pump']['pump_stage'] + " (" + pumpStageDescription[dataset['pump']['vfd_err']] + ")" + } else { + tmp.innerHTML = dataset['pump']['pump_stage'] + } //

Текущий расход: м³

document.getElementById("pump-flow-meter").innerHTML = dataset['pump']['flow_meter'] } -// состояния конченого автомата -// $states = [ -// 0 => "отключен", -// 2 => "инициализация: установка задвижек в начальное состояние", -// 21 => "инициализация: закрытие задвижек 23.5 и 23.6", -// 31 => "инициализация: открытие задвижек 23.5 и 23.6", -// 99 => "авария", -// -// 100 => "ожидание сигнала на перекачку воды", -// -// 102 => "запуск: открытие задвижки 23.6", -// 110 => "запуск: ожидание сигнала от датчика уровня поз.36", -// 121 => "запуск: открытие задвижек насоса", -// 131 => "запуск: закрытие задвижки 23.6", -// 141 => "запуск: пуск ПЧ", -// -// 200 => "работает", -// -// 202 => "остановка: закрытие задвижек 23.3 и 23.4", -// 211 => "остановка: ожидание остановки ПЧ", -// 221 => "остановка: перевод запорной арматуры в исходное состояние", -// 231 => "остановка: работа компрессора", -// 235 => "остановка: сброс конденсата клапанами 25.*" -// ]; diff --git a/templates/index.html b/templates/index.html index 0c27a35..9b48713 100644 --- a/templates/index.html +++ b/templates/index.html @@ -22,15 +22,15 @@ } #canvas-wrapper { - width: 100%; + max-width: 1000px; } .value-good { - color: green; + color: var(--text-good); } .value-bad { - color: red; + color: var(--text-bad); } {% endblock %} @@ -49,9 +49,6 @@

Состояние насосной станции

Последнее обновление:

-

Частота ПЧ: Гц

-

Ток ПЧ: А

-

Ошибка ПЧ:

Регистр аварий:

Состояние КА:

Текущий расход: м³

@@ -60,24 +57,36 @@

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

Последнее обновление:

Текущий уровень воды: %

-

Текущее значение с радара:

Уровень воды

Статус:

-

Уровень воды в резервуаре, %

+
+

Прочие показатели

+

Частота ПЧ: Гц

+

Ток ПЧ: А

+

Ошибка ПЧ:

+

Текущее значение с радара:

+
+
+

Настройки

+
+ + +
+
{% endblock %}