Осциллограф в браузере

Отрисовка графиков в реальном времени

i1dlzuscsiedotordufedlrnp0c.jpeg

Одно время я работал в компании, которая разрабатывала бесконтактные датчики, как на фото. И при установке этих датчиков, надо было правильно сориентировать антенну (белая штука на фото). И выглядело это так: один человек на объекте, где-то в Сибири, на морозе крутит антенну, а другой в Питере, в офисе, не видит того человека, но видит графики на мониторе. И вот они как слепой с глухим пытаются поставить антенну, один по графикам, по телефону говорит, что надо антенну повернуть, а другой пытается понять в какую сторону её крутить. Звучит как бред, правда? Но так и было.
Когда я это всё увидел, понял, что получать графики надо локально и прямо здесь и сейчас наблюдать всю картину, чтобы один и тот же человек видел сигнал и крутил антенну. И понял: надо пилить веб-интерфейс для этой железки. Опыта веб-разработки ноль, значит за одно и поучимся.

Техническое задание


Хоть NDA в той компании я не подписывал, всё же считаю, что разглашать какую-либо информации составляющую коммерческую тайну не имею права. Поэтому постараюсь рассказать в общих чертах.
Как видно на фото выше, мы устанавливали температурные датчики, на высоковольтные шины. Датчики пассивные, работают на фазовом сдвиге обучающей частоты (2,4 ГГц), и пассивно переизлучают эту частоту. Сдвиг частот мы фиксируем и улавливаем. К сожалению, у меня не осталось сырых данных того времени, но выглядят это как некоторые такие «горбы».
Приёмник подключен к промышленному ПК по интерфейсу RS-485, и уже в нём идёт обсчёт и передача данных по интернету на центральный сервер. В целом, приёмник мог бы делать всё сам, но решили для надёжности реализовать таким образом.

f4jabpqszkpsy5sgoiy_g_gmacm.jpeg


Шкаф приёмного оборудования. ПромПК, блок питания, модем и антенна lte.

Таким образом, у нас есть точка входа: промышленный ПК, на котором стоит Linux. В качестве ПК было много различных вариантов использования: как обычные х86+Ubuntu, так и ARM-роутер на OpenWRT. Поэтому решение должно было быть максимально простым универсальным.
Данные со считывателя получала моя программа, которая работала на ПромПК и сохраняла их в csv-файл разделённых табуляциями, где каждый столбец был сигналом с отдельного канала.
Таким образом, надо было просто сделать WEB-интерфейс, и строить график в реальном времени по этому CSV-файлу. Эпизодически пиная считыватель на новую порцию данных.

Реализация


Основа всего алгоритма CGI-bash скрипт (о боже, CGI на bash), который очень прост:

#!/bin/bash
echo "Content-type: text/html;charset=utf-8"
echo
программа_дающая_данные > /var/www/html/result.dat
echo "true" 
exit 0


Следует помнить о том, что все операции происходят от пользователя и группы www-data: www-data (если для апача). Этот момент у меня попил много крови, вообще помните про свои права и права других пользователей, а также про обязанности.
Вызывая этот CGI-скрипт, я каждый раз получаю свежую порцию данных в файле result.dat, которые можем отобразить. Данные выглядят примерно таким образом:

2019	2010	2160	2006	
2023	2052	2041	1992	
2053	2048	2181	1991	
2019	2054	2147	1968	
2003	1977	2189	1982	
2052	1987	2101	1961	
....


Дальше, мне нужно было этот сsv-файл превратить в json. Сделал это с помощью фреймворка Papa Parse, который парсит csv-файл. Построение графика я реализовал на фреймфорке Chart.js. Там громадное количество примеров на вкус и цвет, каждый сможет подобрать подходящее под свою задачу.
Один важный момент: не забывайте очищать массивы, перед внесением новой порции данных. Иначе начинает уплывать память. В момент отладки, на ночь оставил всё, без очищения. Утром пришёл на работу, а мышка уже не в состоянии ползать.

Соберём всё в кучку


Вроде всё просто, осталось всё собрать в единую кучку. Чтобы вам не тратить времени, этот проект я выложил на github github.com/dlinyj/realtime_graph_on_js

Поскольку хочу вам дать рабочий пример, а программа составляет коммерческую тайну, то сделал простенький питоновский скрипт, который генерирует случайные данные для отображения.

#!/usr/bin/env python3
import random
f = open("/var/www/html/result.dat", "w")
for i in range (20):
    f.write("%d\t%d\t%d\t%d\t\n" % (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
f.close()


Основа всего — это CGI на bash, о котором писал выше, который вызывает этот питоновский скрипт.

#!/bin/bash
echo "Content-type: text/html;charset=utf-8"
echo
/usr/bin/python3 /usr/lib/cgi-bin/test.py > /dev/null 2&>1
echo "true" 
exit 0


Исходный код всей веб-страницы можно посмотреть вот тут.

Вначале я конфигурирую параметры самого графика. Это всё взято из готовых примеров фреймворка Chart.js.

Обновление графика делается по таймеру. Каждые 2000 мс идёт вызов функции gen_graph (), которая вызывает CGI-скрипт, описанный выше.

var gen_graphUrl = "cgi-bin/gen_graph.sh";
		function gen_graph() {
			$.ajax({
				url: gen_graphUrl,
				success: function(result) {
					parseData();
				}
			});
		}
		parseData();
		var timerId = setInterval(function() {
			gen_graph();
		}, 2000);
		
		function stop_reload () {
			clearInterval(timerId);
		};


Функция parseData () осуществляет парсинг CSV-данных и преобразование из форматт json:

		function parseData() {
			Papa.parse("result.dat", {
				download: true,
				complete: function(results) {
					createGraph(results.data);
				}
			});
		}


В результате, работа нашего тестового примера выглядит следующим образом:

oq7afjz7aexmh3tkhww3zbqejt0.gif

Заключение


Конечно, весь этот WEB-интерфейс задумывался не только для установки одной антенны. Там было достаточно много другого функционала (прошивка, отладка, добавление коэффициентов), и благодаря этому научился хоть немного программированию на js (хоть понюхал, что это такое). В результате теперь для настройки оборудования нужен только кроссовый кабель и ноутбук. Подключаешь и работаешь в веб-интерфейсе как на обычном роутере. Так же, данный веб-интерфейс доступен по сети, и каждый объект можно отдельно конфигурировать через него, что стало весьма удобно даже людям, далёким от программирования.
Ну и напоследок видео реальных данных с устройства и то, как удобно пользоваться данными графиками.

Ссылки


  1. Репозиторий проекта github.com/dlinyj/realtime_graph_on_js
  2. Фреймворк для построения графиков www.chartjs.org
  3. Фреймворк для парсинга CSV www.papaparse.com

oug5kh6sjydt9llengsiebnp40w.png

3piw1j3wd_cgmzq9sefgferaumu.png

© Habrahabr.ru