ospaz-site/static/js/index-main.js

161 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// скрипт страницы index, на которой отображаются графики
// интервал обновления статуса в миллисекундах
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) {
let out = ""
for (let i = 0; i < desc.length; i++) {
if (desc[i] !== null) {
if ((num & (1 << i)) !== 0) {
// бит установлен
if (out.length === 0) {
out = desc[i]
} else {
out += " + "
out += desc[i]
}
}
}
}
return out
}
/**
* Функция для линейной аппроксимации набора точек. Для заданных точек находит коэфицент a из уравнения y=ax+b.
* Уравнение подбирается при помощи метода наименьших квадратов.
* @param dataset набор точек в виде [[timestamp, val], [timestamp, val], ...], где timestamp - значение по X, val - значение по Y
* @returns {number}, коэфицент a
*/
function approximateWithTimestamps(dataset) {
// для точных расчетов нужно сместить timestamp
const timestamp_offset = dataset[0][0]
// сумма (x[i] * y[i])
let sum_x_mul_y = 0
for (let i = 0; i < dataset.length; i++) {
sum_x_mul_y += (dataset[i][0] - timestamp_offset) * dataset[i][1]
}
// сумма всех x[i]
let sum_x = 0;
for (let i = 0; i < dataset.length; i++) {
sum_x += dataset[i][0] - timestamp_offset
}
// сумма всех y[i]
let sum_y = 0;
for (let i = 0; i < dataset.length; i++) {
sum_y += dataset[i][1]
}
// сумма всех x[i]^2
let sum_x_mul_x = 0;
for (let i = 0; i < dataset.length; i++) {
sum_x_mul_x += Math.pow(dataset[i][0] - timestamp_offset, 2)
}
// вычисление коэфицента a из формулы y=ax+b
// нам нужен только он
return (dataset.length * sum_x_mul_y - sum_x * sum_y) / (sum_x_mul_x - Math.pow(sum_x, 2))
}
async function makeRequest(url) {
let response = await fetch(url)
if (response.status !== 200) {
console.log('fetch(' + url + ') failed. Status Code: ' + response.status);
return null;
}
return await response.json()
}
async function loadAllData() {
return await makeRequest('/fetch/all')
}
async function loadChartData() {
return (await makeRequest('/fetch/tank-chart'))['tank_chart']
}
async function loadLastUpdates() {
return (await makeRequest('/fetch/stats'))['stats']
}
async function updateStatus() {
let dataset = await loadLastUpdates()
// последнее обновление
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)
//<p>Уровень воды <span id="tank-level-dir"></span></p>
const last_radar_values = dataset['tank']['last_radar_values']
if (last_radar_values.length === 0) {
document.getElementById("tank-level-dir").innerHTML = "(?)";
} else {
document.getElementById("tank-level-dir").innerHTML = approximateWithTimestamps(last_radar_values) < 0 ? '↘' : '↗';
}
//<p>Текущий уровень воды: <span id="tank-level-now"></span>%</p>
document.getElementById("tank-level-now").innerHTML = dataset['tank']['last_percentage']
//<p>Текущее значение с радара: <span id="tank-raw-now"></span></p>
document.getElementById("tank-raw-now").innerHTML = dataset['tank']['last_radar']
//<p>Статус: <span id="tank-status"></span></p>
const shur_status_bits = ['нужна вода', 'поплавок нижний', 'поплавок верхний', 'поплавок аварийный']
document.getElementById("tank-status").innerHTML = unpackBits(dataset['tank']['status_reg'], shur_status_bits) + " (" + dataset['tank']['status_reg'] + ")";
//<p>Частота ПЧ: <span id="pump-vfd-freq"></span>Гц</p>
document.getElementById("pump-vfd-freq").innerHTML = dataset['pump']['vfd_freq']
//<p>Ток ПЧ: <span id="pump-vfd-curr"></span>А</p>
document.getElementById("pump-vfd-curr").innerHTML = dataset['pump']['vfd_curr']
//<p>Ошибка ПЧ: <span id="pump-vfd-error"></span></p>
document.getElementById("pump-vfd-error").innerHTML = dataset['pump']['vfd_err']
//<p>Регистр аварий: <span id="pump-alarms"></span></p>
document.getElementById("pump-alarms").innerHTML = dataset['pump']['alarms']
//<p>Состояние КА: <span id="pump-stage"></span></p>
document.getElementById("pump-stage").innerHTML = dataset['pump']['pump_stage']
//<p>Текущий расход: <span id="pump-flow-meter"></span>м³</p>
document.getElementById("pump-flow-meter").innerHTML = dataset['pump']['flow_meter']
}
// состояния конченого автомата
// $states = [
// 0 => "отключен",
// 2 => "инициализация: установка задвижек в начальное состояние",
// 21 => "инициализация: закрытие задвижек 23.5 и 23.6",
// 31 => "инициализация: открытие задвижек 23.5 и 23.6",
// 99 => "<span class=\"value-bad\">авария</span>",
//
// 100 => "ожидание сигнала на перекачку воды",
//
// 102 => "запуск: открытие задвижки 23.6",
// 110 => "запуск: ожидание сигнала от датчика уровня поз.36",
// 121 => "запуск: открытие задвижек насоса",
// 131 => "запуск: закрытие задвижки 23.6",
// 141 => "запуск: пуск ПЧ",
//
// 200 => "<span class=\"value-good\">работает</span>",
//
// 202 => "остановка: закрытие задвижек 23.3 и 23.4",
// 211 => "остановка: ожидание остановки ПЧ",
// 221 => "остановка: перевод запорной арматуры в исходное состояние",
// 231 => "остановка: работа компрессора",
// 235 => "остановка: сброс конденсата клапанами 25.*"
// ];