- PVSM.RU - https://www.pvsm.ru -

Это продолжение статьи про сетевые протоколы используемые с GPS-трекерах. Если в первой части мы обсуждали фрейм декодеры, то во второй части мы посмотрим на варианты кодирование различных типов полезных данных. Многие производители устройств для GPS-мониторинга разрабатывают собственные протоколы прикладного уровня для передачи данных от устройства на сервер, и иногда разработчики прибегают к различным изощренным и не всегда понятным решениям для кодирования данных.
Для тех, кто не читал или забыл первую часть, я напомню, что существуют две основных группы, на которые можно разделить все протоколы: текстовые и бинарные. В текстовых протоколах информация передается в виде ASCII кодов, а в бинарных, соответственно, все данные закодированы в big-endian или, реже, в little-endian бинарном виде.
Порядок от старшего к младшему (big-endian) является стандартным для протоколов TCP и UDP, он используется в заголовках пакетов данных и во многих протоколах более высокого уровня. Поэтому порядок байтов от старшего к младшему часто называют сетевым порядком байтов (network byte order), и он является де-факто стандартом для кодирования бинарных данных в сетевых протоколах.
short i = 1; // 0x00 0x01 - big-endian (network byte order)
// 0x01 0x00 - little-endian
Проблема в том, что центральные процессоры чаще всего используют порядок от младшего к старшему (little-endian), и поэтому многие производители GPS-трекеров решили кодировать данных в том же формате, что данные хранятся в памяти (т.е. little-endian). Список таких производителей достаточно большой, поэтому приведу только несколько примеров: Baltic Car Equipment (BCE, Литовская компания), Cellocator (крупная международная компания с главным офисом в Израиле) и ГалилеоСкай (известный российский производитель GPS-трекеров со штаб-квартирой в Перми).
Некоторые производители идут еще дальше и кодируют часть данных с одним порядком байт, а часть — с другим. Например, устройства китайской компании Topflytech и польского производителя Tytan GPS отсылают все данные в стандартном сетевом порядке байт, кроме чисел с плавающей запятой, которые отправляются в little-endian формате. Справедливости ради следует отметить, что Tytan GPS исправили проблему во второй версии своего протокола.
Координаты (широта от -90° до +90°, долгота от -180° до +180°) могут быть представлены различными способами. GPS-приемники обычно возвращают значение в градусах и минутах с десятичной дробью, при этом положительные координаты представлены буквами «N» (северная широта) и «E» (восточная долгота), а отрицательные координаты — буквами «S» (южная широта) и «W» (западная долгота).
Наибольшее разнообразие вариантов кодирования координат можно встретить в текстовых протоколах. Знак координат может быть представлен либо буквой, либо знаком перед значением в градусах (в некоторых случаях явно указывается положительный знак). Значение может быть представлено либо в градусах с десятичными долями, либо в целочисленных градусах и минутах десятичной дробью. Точки в десятичной дроби могут быть опущены, и разделитель между широтой и долготой может также отсутствовать. Вот, например, несколько вариантов представления для координат Пентагона:
38.870989,-77.055961 // градусы десятичной дробью 3852.25934,N,07703.35766,W // градусы (2 знака для широты и 3 знака для долготы) и минуты десятичной дробью W77.055961,N38.870989 // полушарие и градусы десятичной дробью +38.870989,-77.055961 // явное указание северной широты знаком плюс 3852.2593N07703.3577E // отсутствие разделителя между координатами
В бинарных протоколах географические координаты обычно представлены либо целым числом которое нужно разделить на определенный коэффициент, чтобы получить координаты, либо числом с плавающей точкой (обычно 4 байта).
0x04 0x2b 0x9f 0xa4 -> 69967780 -> ( / 60 / 30000 ) -> 38.870989 // целое число 0xc2 0x9a 0x1c 0xa7 -> -77.055961 // число с плавающей точкой (float)
Знак координаты может храниться отдельно от значения координаты. Например, в протоколе от компании Tzone Digital Technology, биты знаков широты и долготы совмещены со значение направления в 2 байтах данных:
0x03 0x0E // 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0
// | | | направление (9 бит) - 270 градусов
// | | знак долготы - минус (западная долгота)
// | знак широты - плюс (северная широта)
Еще один интересный вариант кодирования координат в бинарных — это двоично-десятичный код (binary-coded decimal или просто BCD). Суть кодирования заключается в том, что каждый десятичный разряд числа записывается в виде его четырёхбитного двоичного кода. Например, широта местоположения Пентагона в протоколах китайских компаний KHD или Gator будет выглядеть следующим образом:
0x03, 0x85, 0x22, 0x59, 0x34 -> 38 градусов 52.25934 минут
Обратите внимание, что запись в шестнадцатеричном виде в точности соответствует значению в десятичном виде. Получается, что данные, закодированные в BCD, относительно легко читаются человеком, но, к сожалению, этот вид кодирования усложняет чтение этих данных компьютером, а также увеличивает размер сообщения.
Подавляющее большинство или даже все протоколы при передаче координат на сервер содержат одну или несколько временных меток. Обычно это время определения координат GPS приемником, но иногда может быть дата и время внутренних часов GPS трекера на момент, когда посылка была сформирована. Некоторые трекеры отправляют две или даже больше временных меток.
В текстовых протоколах практически всегда время и дата разбиты на отдельные компоненты. Вот несколько примеров представления времени последнего перевода часов в России (26 октября 2014, 2 часа ночи):
2014/10/26,02:00:00 // дата и время с разделителями 020000.000,...261014 // время с точностью до миллисекунд 141026...020000 // дата и время без разделителей 20141026020000 14/10/26 2:00 // дата и время с точностью до минут
Важный момент, который стоит отметить — обычно время передается по гринвичу (UTC или GMT временные зоны). Важно это потому, что сервер и трекер могут находиться в разных временных зонах. Некоторые GPS-трекеры позволяют конфигурировать временную зону. При этом часть из них сообщает выбранную временную зону на сервер, а часть — нет. Для тех, которые не сообщают, требуется вручную задавать зону на сервере.
Один интересный пример проблемы с временными зонами — это безымянный протокол, используемый во множестве дешевых трекеров китайского производства. Трекер присылает локальные дату (год, месяц, день) и время (часы, минуты, секунды), а также время с точностью до миллисекунд по Гринвичу. Интересным в данном случае является то, что имея эти данные, можно посчитать дату по Гринвичу для временных зон от GMT-12 до GMT+12. Например, если на входе мы имеем 2016-01-01 01:00:00 (локальное время) и 59:00:00.000 (GMT), то результат на выходе будет 2015-12-31 59:00:00.000 (GMT). К сожалению, этот способ не работает для временных зон с отклонением от гринвича больше 12 часов.
Еще один примечательный вариант представления времени используется в стандартном протоколе TAIP. Время представлено в виде недель, дней и секунд с 6 января 1980 года. Значимость этой даты не совсем понятна, но это стандарт для многих GPS приемников.
Некоторые протоколы передают на сервер только текущее время суток. В данном случае единственное, что можно сделать, это подставить текущую дату по версии сервера. Соответственно это может привести к проблемам, если время сервера и устройства отличается или при любой задержке при передаче данных. Например, устройство может передать время 23:59:59, а при приеме этого сообщения на сервере уже будет начало следующего дня. Один вариант обхода этой проблемы — это сравнение полученной временной метки с текущим временем сервера, и если разница получается больше часа или нескольких часов, то нужно прибавить или отнять один день от полученной даты.
В бинарных протоколах дата и время либо разбиты на отдельные компоненты так же, как и в текстовых, либо хранятся в виде временной метки UNIX (количество секунд или миллисекунд с полуночи (00:00:00 GMT) 1 января 1970 года).
Вся информация, представленная в данной статье, была накоплена по ходу работы над сервером GPS-мониторинга. Проект полностью Open Source, и если кому-нибудь интересно, то исходный код с реализацией всех приведенных протоколов можно найти на GitHub [1].
Также кого-то может заинтересовать документация на протоколы для GPS-трекеров [2]. К сожалению, все имеющиеся документы не могу опубликовать в открытом доступе, так как некоторые из них конфиденциальные.
Автор: tananaev
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/106247
Ссылки в тексте:
[1] GitHub: https://github.com/tananaev/traccar
[2] документация на протоколы для GPS-трекеров: https://www.traccar.org/protocols/
[3] Источник: http://habrahabr.ru/post/273127/
Нажмите здесь для печати.