Немного решил затронуть интересную тему с работой с GPS приемниками под Linux и в частности на Raspberry Pi, как наиболее популярной IoT платформе с Linux. Не всегда есть возможность подключить Raspberry Pi к интернету, чтобы синхронизировать время с NTP серверами точного времени, которые в свою очередь транслируют это время со спутников GPS, но иногда в проект бывает заложен собственно GPS приемник и почему бы не брать время напрямую со спутника и не записывать его в Raspberry Pi, так мы и сделаем, будем использовать стандартный C и демон gpsd, про который наверное не много, кто слышал.
Итак, что же такое gpsd? А это небольшой демон, который мониторит данные, поступающие с одного или нескольких приемников GPS, подключенных по USB к Linux компьютеру и отдает эти данные по запросу в порт 2947 хост машины. Из хорошего, формат. отдаваемых демоном данных, значительно проще и понятней для анализа нежели тот же NMEA 0183. Работать с ним не просто, а очень просто, существует C библиотека для линковки с приложением, также есть C++ класс-обертка для этой же библиотеки и даже Python модуль, для любителей скриптов. Все это и немного документации можно найти на официальной страничке gpsd.
Система GPSD также поддерживает хранение точного времени; она может выступать в качестве источника времени для
ntpd
(демона протокола сетевого сервиса времени), если в каком-нибудь из подключенных к нему датчиков имеется возможность выдавать сигналы PPS (секундные сигналы). Разработчики проекта GPSD тесно сотрудничают с проектомntpd
с целью улучшения сетевого сервиса времени.
Вот что интересного говорит нам документация к gpsd. Для тех, кто хотел бы немного глубже копнуть по сабжу, вот перевод из книги «Архитектура приложений с открытым исходным кодом» главы 7, которая как раз затрагивает gpsd.
А теперь попробуем использовать это для решения задачи получения точного времени и установки оного в Raspberry Pi.
Я использовал небольшой GPS приемник на базе Quectel L76, который сам же и сваял на коленке:
Подключение к Raspberry Pi по USB через, встроенный в плату, конвертер Serial-To-Usb CP2102.
Далее приведу отрывок программы, который как раз касается приема данных от демона и установки NTP времени на Raspberry Pi:
#include <stdio.h> #include <gps.h> #include <time.h> int rc; struct timeval tv; struct gps_data_t gpsData; int main(void) { if ((rc = gps_open ("localhost", "2947", &gpsData)) == -1) { printf ("[ERROR] No GPS receiver found. code: %d, reason: %s\n", rc, gps_errstr(rc)); return EXIT_FAILURE; } gps_stream(&gpsData, WATCH_ENABLE | WATCH_JSON, NULL); // Ждем пару секунд пока будут приняты данные GPS if (gps_waiting (&gpsData, 1000000)) { // Читаем данные с GPS приемника if ((rc = gps_read(&gpsData)) == -1) { printf ("[ERROR] Error occured reading gps data. Code: %d, reason: %s\n", rc, gps_errstr(rc)); } else { // Показать данные GPS приемника if ((gpsData.status == STATUS_FIX) && (gpsData.fix.mode == MODE_2D || gpsData.fix.mode == MODE_3D) && !isnan(gpsData.fix.latitude) && !isnan(gpsData.fix.longitude) && !isnan(gpsData.fix.altitude)) { printf ("[INFO] Latitude: %.2f Longitude: %.2f Altitude: %.1f Timestamp: %ld\n", gpsData.fix.latitude, gpsData.fix.longitude, gpsData.fix.altitude, (time_t)gpsData.fix.time); struct timeval gpstv; gpstv.tv_sec = (time_t)gpsData.fix.time; gpstv.tv_usec = 0; settimeofday (&gpstv, NULL); } } while (1) {} return 0; }
Создаем сперва экземпляр структуры gps_data_t:
struct gps_data_t gpsData;
Далее, открываем порт 2947 на чтение данных GPS:
if ((rc = gps_open ("localhost", "2947", &gpsData)) == -1)
Читаем данные:
if ((rc = gps_read(&gpsData)) == -1)
И устанавливаем время:
settimeofday (&gpstv, NULL);
Попутно программа выводит в консоль координаты, принятые от приемника, и время в формате unixtime:
printf ("[INFO] Latitude: %.2f Longitude: %.2f Altitude: %.1f Timestamp: %ld\n", gpsData.fix.latitude, gpsData.fix.longitude, gpsData.fix.altitude, (time_t)gpsData.fix.time);
Координаты далее можно использовать как угодно в программе, опрос порта 2947 можно вести непрерывно через равные промежутки времени в цикле while (1) и далее математически пересчитывать координаты для определения местоположения каких либо объектов относительно вашего местоположения, например, самолетов, что очень даже используется в ADSB приеме (азимут, угол места, дальность и т.д.).
Вот и все, репостните, пожалуйста, ссылку на данный материал, кнопочки слева)