G

gpsdPROXY

Категория проекта: Ожидает модерации
Темы: gpsd gps AIS
+ ещё 5
PHP демон, расширяющий возможности gpsd за счёт указания пользовательской "эпохи" для каждого типа данных

In English

gpsdPROXY daemon License: CC BY-NC-SA 4.0

version 0.6

Весьма удобно обращаться к gpsd из веб-приложений посредством команды ?POLL; в произвольный момент времени, однако есть проблемы:

во-первых, данные AIS недоступны в команде ?POLL;
во-вторых, данные, отличные от тех, что отдаёт приёмник ГПС, могут не попасть в команду ?POLL;

Причина в том, что gpsd собирает данные в течение "эпохи" от одного получения координат приёмником ГПС до другого. Но "эпоха" для данных AIS и приборов гораздо длиннее, и эти данные не попадают в запрос ?POLL;
С деталями и дискуссией по этому поводу можно ознакомиться по следующим ссылкам (англ.):
https://lists.nongnu.org/archive/html/gpsd-users/2020-04/msg00093.html
https://lists.nongnu.org/archive/html/gpsd-users/2021-06/msg00017.html

Однако надо заметить, что gpsdPROXY довольно странная программа, потому что она, в общем, делает ровно то же самое, что и собственно gpsd: собирает данные из потока, агрегирует их и отдаёт структурированные данные по требованию. Разница во времени жизни данных. В gpsdPROXY его можно задавать явным образом для каждого типа данных. Думаю, что такая функциональность должна быть непосредственно в gpsd. Но этого нет.
Зато можно применить gpsdPROXY для сбора данных от источников, в которых нет контроля достоверности данных. Например, от VenusOS, где нет совсем никакого контроля, и от SignalK, где есть хотя бы метка времени. Или просто использовать gpsdPROXY как websocket интерфейс к gpsd.
Дополнительно gpsdPROXY может получать и потом раздавать клиентам информацию "Человек за бортом", а также определять возможность столкновения с целями AIS.

Возможности

Предлагаемый демон собирает данные AIS и всё то, что передаётся gpsd в секции TPV и хранит их в течение указанного пользователем времени. Получить данные можно запросом ?POLL; протокола gpsd.
Таким образом, все данные AIS и данные эхолота и анемометра (и ГПС, конечно) становятся доступными в произвольный момент времени.

Дополнительно реализован и синхронная потоковая отдача данных, аналогичная режиму ?WATCH={"enable":true,"json":true} gpsd.

Источники данных

Основным источником данных для gpsdPROXY является gpsd, запущенный на той же или другой машине. При использовании gpsd обеспечивается максимальная достоверность данных.
Однако, можно получать данные и из других источников, таких как:

VenusOS

gpsdPROXY может работать под управлением VenusOS по крайней мере начиная с версии v2.80~38, и во всяком случае на Raspberry Pi. Работа в устройствах Victron Energy не проверялась. Однако, gpsdPROXY может получать данные от любого устройства в сети, работающего под управлением VenusOS любой версии.
Для того, чтобы gpsdPROXY мог получать данные, нужно сделать следующие настройки в VenusOS:
В веб-консоли или на экране управления устройства открыть пункты меню Settings -> Services -> MQTT on LAN (SSL) и указать "Включить".

Ограничения
  • в VenusOS нет данных о глубине и нет данных AIS
  • данные, представляемые VenusOS не являются достаточно достоверными и должны использоваться с осторожностью

Signal K

gpsdPROXY может получать данные от сервиса Signal K, работающего на той же машине, или в локальной сети. gpsdPROXY предпримет попытку самостоятельно найти Signal K посредством zeroconf, или обращаясь на стандартный порт. Но лучше сконфигурировать.

Ограничения

На самом деле gpsdPROXY к SignalK должен обращаться только локально. Через сеть -- оно странное.

Обнаружение столкновений

gpsdPROXY определяет возможность столкновений с целями AIS, а зависимости от их и от собственной скорости и указанного времени до события.
collision model

Возможность столкновения вычисляется в соответствии с примитивной моделью движения, учитывающей, фактически, только возможные отклонения от курса. Однако ожидается, что эти вычисления не должны критически загрузить сервер даже при большом количестве целей AIS.
Объект ``{"class":"ALARM","alarms":{"collisions":[]}}` содержит список mmsi и координат потенциально опасных судов. GaladrielMap обозначает такие объекты на карте специальным значком, а у курсора собственного положения рисует стрелочки с направлением на опасный объект.
Для корректной работы надо указать характеристики своего судна в params.php.

Совместимось

Linux, PHP < 8. Кретинские решения, принятые в PHP 8 не позволяют gpsdPROXY работать под PHP 8, а я не хочу следовать этим решениям.

Настройка

См. файл params.php

Использование

$ php gpsdPROXY.php

К демону можно подключиться через BSD socket или websocket по адресу, указанному в params.php.

Управление

Демон проверяет, не запущен ли он уже, и не запускается вторично.
Параметры команд gpsd не поддерживаются, зато имеются дополнительные параметры:

  • параметр "subscribe":"TPV|AIS" для команд ?POLL и ?WATCH={"enable":true,"json":true}.
    Параметр указывает возвращать только данные TPV или AIS, но не то и другое. Например:
    ?POLL={"subscribe":"AIS"} возвращает класс "POLL" с данными "ais":[], вместо "tpv":[].
  • параметр "minPeriod":"", в сек. для команды WATCH={"enable":true,"json":true}. Нормально данные отсылаются так часто, как они приходят от gpsd. Указание этого параметра заставляет демон отсылать данные не чаще указанного количества секунд. Например, команда:
    WATCH={"enable":true,"json":true,"minPeriod":"2"} посылает данные каждые две секунды, или реже, по мере получения данных.

Результат

Демон возвращает данные, как описано в документации к gpsd, за исключением:

  • ответ DEVICES на команду WATCH содержит только одно устройство -- сам демон. Как следствие -- не надо объединять сходные данные от разных устройств: это уже делает демон.
  • массив sky в объекте POLL пуст
  • объект AIS отсутствует в ответе команды WATCH, вместо этого посылается отдельный объект
  • в объект POLL и ответ команды WATCH добавлен массив ais с ключами mmsi и данными в формате, описанном в AIS DUMP FORMATS, за исключением:
  • скорость в м/сек
  • координаты в десятичных градусах
  • углы в градусах
  • осадка в метрах
  • длина в метрах
  • ширина в метрах
  • поле 'second' отсутствует, но есть поле 'timestamp' с временем unix

Пример клиентского кода

webSocket = new WebSocket("ws://"+gpsdProxyHost+":"+gpsdProxyPort);

webSocket.onopen = function(e) {
	console.log("spatialWebSocket open: Connection established");
};

webSocket.onmessage = function(event) {
	let data;

	data = JSON.parse(event.data);

	switch(data.class){
	case 'VERSION':
		console.log('webSocket: Handshaiking with gpsd begin: VERSION recieved. Sending WATCH');
		webSocket.send('?WATCH={"enable":true,"json":true,"subscribe":"TPV,AIS,ALARM","minPeriod":"0"};');
		break;
	case 'DEVICES':
		console.log('webSocket: Handshaiking with gpsd proceed: DEVICES recieved');
		break;
	case 'WATCH':
		console.log('webSocket: Handshaiking with gpsd complit: WATCH recieved.');
		break;
	case 'POLL':
		break;
	case 'TPV':
		realtimeTPVupdate(data);
		break;
	case 'AIS':
		realtimeAISupdate(data);
		break;
	case 'ALARM':
		for(const alarmType in data.alarms){
			switch(alarmType){
			case 'MOB':
				realtimeMOBupdate(data.alarms.MOB);
				break;
			case 'collisions':
				realtimeCollisionsUpdate(data.alarms.collisions);
				break;
			}
		}
		break;
	}
};

webSocket.onclose = function(event) {
	console.log('webSocket closed: connection broken with code '+event.code+' by reason ${event.reason}');
};

webSocket.onerror = function(error) {
	console.log('webSocket error');
};

Поддержка

Сообщество ВКонтакте

Индивидуальная платная консультация

Вы можете сделать пожертвование через ЮМани.