dlinyj: (Default)
[personal profile] dlinyj
Первый тост за локалхост
Я знаю отличную шутку про UDP, но не факт, что она до вас дойдет.
Я знаю отличную шутку про TCP, но если она до вас не дойдет, то я повторю.
А кто знает отличную шутку про ARP?


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

Одно из важных условий, вся красота должна работать без интернета. Поэтому всякие java-скрипты, которые ведут в дальние дальние сайты - не подходят. Т.е. локально должно быть.
Я тут попробовал gnuplot в веб, по посту.



Одна из крутейших фишек: можно зумить графики, отключать лишние каналы и т.п. Что нам очень нужно, т.е. интерактивно с ними взаимодействовать. Из минусов, прям существенных - это то, что на систему нужно ставить gnuplot, а это может быть openwrt и версия может не давать web-графики. Плюс надо несколько графиков на странице и обновнять их.

php-скрипт страницы прост до безумия:



Сам гнуплотовскй скрипт выглядит так:

#! /usr/bin/gnuplot -persist
set terminal canvas enhanced mousing jsdir 'js'
set grid xtics ytics
plot 'result.dat'	using 1 w l t "Ch 1", \
	'' using 2 w l t "Ch 2", \
	'' using 3 w l t "Ch 3", \
	'' using 4 w l t "Ch 4", \
	'' using 5 w l t "Ch 5", \
	'' using 6 w l t "Ch 6", \
	'' using 7 w l t "Ch 7", \
	'' using 8 w l t "Ch 8", \
	'' using 9 w l t "Ch 9", \
	'' using 10 w l t "Ch 10", \
	'' using 11 w l t "Ch 11", \
	'' using 12 w l t "Ch 12", \


На самом деле, нужно сделать чтобы вызывалась внешняя программа регулярно, которая будет заполнять этот "result.dat", а потом вызывать сам гнуплот, а на вебстраничке это бы обновлялось. Это типа ajax-запрос. У меня стойкое чувство, что я изобретаю велосипед, и есть готовые решения из коробки, с построением графиков, запуском приложенией и загрузкой файлов. Потыкайте носом. Дизайн роли большой не играет.
Функциональный дизайн примерно такой:



Кнопки вызывают программу (бинарь), с параметрами радиобатонов/чекбоксов и полей ввода.

Date: 2018-10-26 10:53 am (UTC)
From: [identity profile] gudronoed.livejournal.com
Это невыполнимая задача в реальном времени. Либо время нереальное, либо квантование.

Date: 2018-10-26 10:59 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Скажем так, там квантование, каждая точка 1274 значения, их надо строить на графике. Точка снимается, ну пусть раз в секунду. Т.е. не так уж часто.
Edited Date: 2018-10-26 10:59 am (UTC)

Date: 2018-10-26 11:09 am (UTC)
From: [identity profile] gudronoed.livejournal.com
И в чем тогда задача? Берешь JavaScriptы нелюбимые, берешь сервак на nodejs поднимаешь там socket.io и все.

Date: 2018-10-26 11:11 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Надо чтобы было как можно проще, и работало на всяких openwrt

Date: 2018-10-26 11:13 am (UTC)
From: [identity profile] gudronoed.livejournal.com
Какие еще openwrt. Вот это вот "запустить бинарник регулярно, заполнить файл result.dat" - это решение эпохи мезозоя. Еще и gnuplot какой то наверняка еще вернером фон брауном написанный.
- https://nodejs.org/ туда где есть данные
- https://socket.io/ на node.js и в браузер (инторнет не нужен, все будет работать локально)
- jquery / что нибудь в бразере для построения графика

Edited Date: 2018-10-26 11:15 am (UTC)

Date: 2018-10-26 11:22 am (UTC)
From: [identity profile] dlinyj.livejournal.com
В любом случае под капотом приложуха, которая взаимодействует с датчиками.

Date: 2018-10-26 11:27 am (UTC)
From: [identity profile] gudronoed.livejournal.com
А оттуда как данные вытащить? из приложухи?

Date: 2018-10-26 11:30 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Они делают выхлоп либо в файл, либо в консоль

Date: 2018-10-26 11:31 am (UTC)
From: [identity profile] gudronoed.livejournal.com
В консоль шикос. Тогда можно форкнуть прилагу из консоли и напрямую парсить stdout в node.js проще не придумаешь!

Date: 2018-10-26 11:32 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Только nodejs ваще для меня тёмнейший лес. Даже с какого края подходить не знаю.

Date: 2018-10-26 11:35 am (UTC)
From: [identity profile] gudronoed.livejournal.com
Ну я могу подсказать куда чего если займешься. Было бы время написал бы, но увы не смогу этим заняться. А направить смогу.

Date: 2018-10-26 12:02 pm (UTC)
From: [identity profile] mbr.livejournal.com
Вчера ты наезжаешь на малый бизнес.
Сегодня ты пишешь на php.
Что завтра? Смузи и макбук в кредит?

Date: 2018-10-26 12:12 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
Взоржал. Ладно, мир дружба жвачка. Лучше по сути скажи, где искать?

Date: 2018-10-26 12:34 pm (UTC)
From: [identity profile] mbr.livejournal.com
Тю. Как быстро ты слился. У меня то на страницу нафлудил :)

А по сути. Я бы смотрел в сторону демона, который параллельно висит, дергает консоль и по сокету картинку отдает. Чего там под openwrt нынче модно? lua? А в браузере уже жабаскрипт, который периодически картинку обновляет.

Date: 2018-10-26 04:26 pm (UTC)
From: [identity profile] Николай Замотаев (from livejournal.com)
В родном вебинтерфейсе openwrt уже есть модуль с графиками:
https://github.com/openwrt/luci/tree/master/modules/luci-mod-status/luasrc/view/admin_status
и
https://github.com/openwrt/luci/blob/master/modules/luci-mod-status/luasrc/controller/admin/status.lua

Date: 2018-10-26 07:29 pm (UTC)
From: [identity profile] 5kopejek.livejournal.com
Помоему в ТЗ логическое противоречие

>>Есть удалённая машина (промышленный ПК или аналогичное под линуксом)
>>Одно из важных условий, вся красота должна работать без интернета.

Не?

Date: 2018-10-27 10:46 am (UTC)
From: [identity profile] gray-bird.livejournal.com
Кроме инета бывает еще интранет, дискоммуницированный с большим миром!

Date: 2018-10-28 07:05 am (UTC)
From: [identity profile] masterspammer.livejournal.com
Графику вообще можно рисовать на клиенте (в браузере) - например так: https://github.com/d3/d3/wiki/Gallery

Отдавать новую порцию js можно просто - long polling или вообще
выводить в поток длинный (потенциально бесконечный) html файл, в нём вставки в теге скрипт каждая, содержат новые данные;
на клиенте просто этот html открыт в невидимом iframe, откуда дёргает основной "получи, мол, данных кусок, хозяин".

Некрасиво, но шустро и НИЧЕГО на сервере не требует, лишь бы оно print умело в той или иной форме.

Date: 2018-10-28 07:08 am (UTC)
From: [identity profile] masterspammer.livejournal.com
P.S. На сервере лежит статический index.html и немного не менее статических js. Никакого внешнего интернета им не надо.

Там же всего один скрипт - он или умеет отдавать новый кусочек данных (а js его каждый раз запрашивает), это типа long polling
или он постепенно отдаёт простыню html (пустую) со скриптовыми вставками. Всё. Основная логика на js.

Date: 2018-11-06 12:57 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
Очень хорошо было бы простейший пример. Где данные отдаются, формируется и т.п. Всё красиво на словах, но как всё собрать в кучу - не представляю.

Date: 2018-11-07 02:25 am (UTC)
From: [identity profile] masterspammer.livejournal.com
Итак, пример простейший:
index.html:
<html><head><title>A sample</title>
<script type="text/javascript" src="/index.js"></script></head>
<body onload="m_init()">
<p>loading...</p>
<iframe style="width:1px;height:1px;border:none;visibility:hidden" src="/index.cgi"></iframe>
</body>

index.js:
function m_init(){
/// подготовить и нарисовать
}
function m_update(a_piece){
/// добавить кусочек данных
}
function m_reset(){
// удалить и начать всё с начала
}

index.cgi: (тут пишу не код, а то, что этот код пишет в поток вывода, первая строка - есть или нет в зависимости от сервера, настроек и может быть имени скрипта (см. nph-скрипты в apache))
HTTP 200 OK
Content-Type: text/html

<html><head>
<script type="text/javascript">
parent.m_update(['данные'])
</script>
<!-- вот тут скрипт ничего не делает, висит N секунд, пока ещё данные не придут -->
<script type="text/javascript">
parent.m_update(['ещё данные'])
</script>
<!-- и ещё висит N секунд -->
<script type="text/javascript">
parent.m_update(['ещё данные'])
</script>
<!-- и ещё висит N секунд -->
<script type="text/javascript">
parent.m_update(['ещё данные'])
</script>
<!-- и ещё висит N секунд -->
<script type="text/javascript">
parent.m_update(['ещё данные'])
</script>
<!-- и ещё висит N секунд -->
<script type="text/javascript">
parent.m_update(['ещё данные'])
</script>
<!-- и ещё висит N секунд -->
<script type="text/javascript">
parent.m_reset() // видать всё сильно поменялось
</script>

<!-- чтоб соединение не протухло, пусть будет выводить пробел раз в несколько секунд -->
<!-- а буферизировать отдачу в сокет тут лучше не надо -->

<script type="text/javascript">
parent.m_update(['данные'])
</script>

<!-- и так далее в цикле... до строк ниже скорее всего дело не дойдёт -->
</head></html>

Edited Date: 2018-11-07 02:26 am (UTC)

Date: 2018-11-07 02:31 am (UTC)
From: [identity profile] masterspammer.livejournal.com
Итого - в невидимый iframe грузится длииинный html и делает это очень долго; в этом html - вставки скриптов, передающих "наверх" родителю новые данные по мере их поступления.

Тут ещё я может быть налажал с инициализацией, можно вообще её из body onload убрать, а в iframe скинуть:

<script type="text/javascript">
parent.m_init()
</script>

А загрузку в iframe начинать не сразу, а скриптом или тупо ссылкой
<a href="/index.cgi" target="name_of_iframe_i_forget_to_add_above">Старт!</a>

Если html в iframe становится сильно длинным, его можно перезагружать автоматически время от времени.
Edited Date: 2018-11-07 02:32 am (UTC)

Date: 2018-11-07 09:33 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Гениально! Гениально!!!!

Всё это должно кончится, когда кончится память.

Date: 2018-11-07 09:34 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Гениально!!! Надо обязательно попробовать.

Date: 2018-11-07 09:34 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Я всячески растекаюсь в благодарностях!!!

Date: 2018-11-07 10:28 am (UTC)
From: [identity profile] masterspammer.livejournal.com
От переполнения html спасает hiddenframe.location.href='/index.cgi?' + random_number раз в какое-то число событий (особенно красиво в обработчике самого события и вызывать) или секунд, но это уже чуть за границами нормального примера. Так же можно тут сделать красиво - '/index.cgi?' + last_event_id чтоб избежать потери данных.

От переполнения самих данных спасает например очередь (хранить только последних 1000 чисел).

Да, ещё раз скажу - все графики и т.д. рисуются НА КЛИЕНТЕ и только на нём.

Date: 2018-11-07 10:30 am (UTC)
From: [identity profile] masterspammer.livejournal.com
Я пробовал - пашет!
Python или perl, apache.
Даже с детектором обрыва сети.
Код не сохранял, но он тривиален - в основном из print()

Date: 2018-11-07 10:35 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Тут сразу ещё один вопрос, а что если мне нужно ещё и отдавать параметры в этот cgi?

Date: 2018-11-08 02:04 am (UTC)
From: [identity profile] masterspammer.livejournal.com
Как минимум два варианта:
1. перезагружать тот же index.cgi, передавая параметры ему
2. вызывать какой-то скрипт "в никуда" (AJAX, target=none и т.д.), а процессы на сервере как-то сами договорятся (pipe, сигналы и т.д.)

January 2026

S M T W T F S
    123
456 78910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 22nd, 2026 05:56 pm
Powered by Dreamwidth Studios