Привет, меня зовут Павел, я программист-эксперт в отделе разработки серверных решений ЮMoney. Это не первая моя статья для блога компании на Хабре — уже выходило два текста о том, как и во что эволюционировали наши конечные автоматы (Часть 1 и Часть 2), вы их очень тепло приняли. В этот раз речь пойдёт про неожиданные проявления моего увлечения программированием. Когда-то у меня получилось сделать GPS-трекер для соревнований по спортивному ориентированию. Хочу поделиться этой историей и рассказать, во что этот GPS-трекер превратился за 17 лет.
С чего всё начиналось
В 2008 году я написал GPS-навигатор для J2ME-совместимых телефонов с возможностью видеть местоположение других пользователей в режиме реального времени. Если отставание и было, то не больше секунды.

Тогда же я познакомился с людьми, которые занимаются спортивным ориентированием, и их очень заинтересовала возможность видеть и отслеживать местоположение участников соревнований с помощью моего устройства. Подобное мы видели, только когда приезжали на соревнования типа Jukola и Halikko в Финляндии, в России такого ещё не было.
Хочу отдельно отметить Алексеева Александра Викторовича. Это один мой близкий человек, который проводил ежегодные соревнования под названием «Алек». Там было и спортивное ориентирование, на котором мы стали применять мою программу в качестве GPS-трекера.
Мы обсудили, что нам ещё требуется, чтобы начать использовать приложение, а что у нас уже есть. Доработали трансляцию местоположения участников на большом экране, перенесли приложение на Android в той части, что была нужна для соревнований. Это когда стало понятно, что J2ME уже «всё»: мир тогда перешёл на iPhone и Android.
Но у нашей схемы обнаружилось слабое место — нужно было покрыть местность в районе проведения соревнований сотовой связью приемлемого качества. Ведь когда в лес, где есть только Edge (цифровая технология беспроводной передачи данных для мобильной связи), съезжается минимум полтысячи человек, у каждого из которых свой сотовый телефон, связь становится плохой.
Эту проблему мы решали по-разному. В центре слежения за участниками соревнований стали подключаться к интернету через спутник, а данные с телефонов передавать по сетевому протоколу UDP, потому что телефоны могли отправлять UDP-пакеты. Но, чтобы показать на экране общую картину — местоположение участников соревнований на карте в режиме реального времени, — нужно было самому иметь надёжное подключение к серверам.
Что было дальше
Соревнования по спортивному ориентированию проходили ежегодно, и так, начиная с 2010 года, параллельно я исправлял обнаруженные ошибки в GPS-трекере. В итоге к 2014 году при наличии сотовой связи показ местоположения участников соревнований на карте в режиме реального времени работал хорошо, нас уже почти всё устраивало. Оставался только один недостаток: в каждом телефоне должна была быть SIM-карта, а за неё нужно было платить сотовому оператору. ?

Теперь немного о том, что удалось сделать в клиентском приложении для удобного просмотра карты на экране. Приложение было под Windows, а формат карт — те же тайлы, что и в онлайн-картах. Соответственно, карты легко кэшировались с веба, но можно было подложить и свою карту, которую надо было всего лишь нарезать тайлами. Такая программа была сделана ещё с начала разработки J2ME-приложения, так как всем хотелось, чтобы у них локально на телефоне были качественные отечественные топографические карты известного происхождения. Такие карты есть в интернете в отсканированном растровом формате, они привязаны к координатам в OziExplorer. Конвертор нарезал их на тайлы и упаковывал в специальный формат, который использовало J2ME-приложение. Позднее ими могло пользоваться и клиентское приложение для онлайн-просмотра во время трансляции соревнований.
В клиентском приложении можно было менять масштаб, карту, имена участников, длину следа трека. И делать это так, чтобы зрители не видели манипуляций оператора, ведь всё происходило в прямом эфире.
Собственно, эта наша история остановилась, как только не стало вышеупомянутой компании «Алек», которая проводила соревнования и на которую были оформлены SIM-карты участников. А ещё к тому моменту появилась и параллельно развивалась другая система, которую специально делали в O-GPS Center под разные виды ориентирования в спорте. Она была простой и доступной для публичного использования.
Неожиданный разговор
Летом 2023 года я участвовал в соревнованиях по спортивному ориентированию — «Камни Карельского Перешейка». Там разговорились с Денисом, сотрудником O-GPS Center, обсудили, почему их трекеры до сих пор работают на сотовой связи, ведь есть же разные радиомодемы и, возможно, что-то ещё. За сотовую связь нужно платить, а держать сотню активных SIM-карт — отдельная забота. Денис рассказал про LoRaWAN — это такая технология для передачи небольших данных на относительно большие расстояния.
На Хабре есть статьи и про саму технологию (например, вот эта), и про разные тесты дальности работы (например, такая). Но, конечно, пока сам не попробуешь, не поймешь, насколько это подходит для интересующей нас области применения — LoRa + GPS (или, как теперь правильнее писать, GNSS).


Конечно, идея такой связки была не нова. На Хабре я сразу нашел несколько статей на эту тему, самой информативной для меня оказалась вот эта. Её автор развивает свои устройства и инструменты для мониторинга. Мы познакомились с ним и по ходу моей разработки стали активно взаимодействовать в его Telegram-чате, помогая друг другу решать разного рода задачи.
Аrduino... Как много раз я слышал это слово
Слышал, но при этом ни разу не использовал платформу и не имел понятия о микроконтроллерах. Да, я программировал много лет, но исключительно под персональные компьютеры. Поскольку взаимодействовать с модулем LoRa должно что-то весьма компактное и мобильное, выбор был очевиден. А поскольку это был эксперимент, решение начать с Аrduino показалось логичным: это простой и быстрый способ продвигаться вперёд.
Поиск похожих решений тоже сразу привёл меня к этой платформе. Первое, что я нашёл, была свежая статья на Хабре (AGLoRa. Или прототип простого самодельного спутникового LoRa-трекера), а затем — другой текст того же автора (AGLoRa 2.0 Вторая версия LoRa трекера. Всё сломать и переделать). Что важно, у Евгения, автора этих материалов, оказалось готовое приложение для телефона — в дальнейшем это сильно облегчило мне проверку работоспособности первых сборок в полевых условиях. Приложение до сих пор есть в свободном доступе на GitHub, вот ссылка.
Я сразу пошёл на маркетплейсы и заказал несколько разных наборов с Аrduino, чтобы прощупать то, что есть в мире микроконтроллеров: кнопки, светодиоды, UART... Пришлось вспомнить базу по С++. Заказал также модули LoRa типа E433T30D, достаточно мощные, чтобы понять сходимость решения в целом. В итоге, собрав это всё на макетках (макетная плата), поработав с Arduino Uno и Nano и намучившись с делителями напряжения, я понял, что моя схема должна будет жить на 3.3В. Первым микроконтроллером, который я взял в сборку первого рабочего прототипа, стал Arduino Mino Pro 3.3В. С ним схема сразу упростилась и работалось ничуть не хуже, хотя производительность была в два раза ниже, чем у варианта с 5В.
Знакомство с трассировкой плат — EasyEDA
Итак, у меня всё заработало на макетках, но как собрать рабочий прототип, который не рассыпается в кармане? Хорошо бы всё это запаять да спрятать в корпус!
Пока разбирался с платформой Аrduino, я наткнулся на ресурс, где рассматривается множество нюансов работы с ней. В том числе есть обучающие материалы по трассировке плат на EasyEDA. Надо ли говорить, что плату для первого прототипа я сделал за один вечер? Ок, скажу, что сделал за два. ? Решение было реализовано почти что «в лоб»: я перенёс всё с макетной платы как есть, не заботясь о каких-то других моментах, и уже через пару недель держал в руках свои первые печатные платы. Какими же классными они мне казались — я с трудом верил, что такое можно сделать так просто.


В итоге пришлось перебрать с десяток промежуточных дизайнов (и почти все напечатать, спаять и протестировать), прежде чем прийти к тому, что есть сейчас. Я использовал микроконтроллер Arduino Pro Micro 3.3V. Его готовый USB-порт сильно облегчает отладку уже готового устройства. Для связи с телефоном перешёл на BLE, представляемый готовым модулем JDY-19 с очень низким энергопотреблением.
Принципиальная схема трекера получилась такая:

Для компактности на плате разместил компоненты с двух сторон:

В итоге получилось такое устройство:

Здесь можно посмотреть схему трекера, а здесь — схему и плату для ретранслятора.
Пути в ссылках для проектов получились некрасивыми (если вы скопируете ссылку со слова «здесь» из предыдущего предложения, то увидите, о чём речь), но в таком виде у меня EasyEDA создавала проекты новых версий из старых. ?♂️
Прошивка для самого трекера и ретранслятора — тут.
В редакторе ретранслятор выглядел вот так:

Сделал побольше держателей батарей, чтобы можно было при необходимости увеличить время автономной работы.
От прототипа к решению
Конечно, то, что я собрал на платах первой версии, годилось только для лабораторных испытаний. Я стал искать варианты, как уменьшить размеры и разместить всё в корпусе, стал продумывать удобство перепрошивки и перенастройки.
Чтобы сделать вещь, которой будет удобно пользоваться, требовалось решить ещё с десяток важных вопросов.
Выбрать микроконтроллер. С Arduino Pro Mini 3.3V оказалось не так удобно работать: программирование через UART, нет возможности примитивно отлаживаться через вывод из-за единственного хардового Serial. В итоге выбор пал на Arduino Pro Micro 3.3V, работать с которым гораздо комфортнее, что ведёт к резкому повышению производительности. Наблюдение за выводом всей необходимой отладочной информации помогло быстро решать возникающие проблемы с кодом прошивки.
Выбрать аккумулятор. В первые образцы я всё еще ставил аккумулятор 18650, но с ним так и не получилось уложиться в размеры, к которым я стремился. В итоге я взял аккумулятор 14500. Долго перебирал имеющиеся в продаже держатели батарей, пока не нашел такой, из которого невозможно случайно вытряхнуть батарею.
Сделать зарядку аккумулятора. Мне было важно, чтобы была возможность быстро сменить аккумулятор, поэтому, поиграв с разными модулями зарядки, я в итоге вообще выкинул их из схемы.
Питание модуля E433T30D желательно было сделать 5В. По словам производителя, так можно добиться максимальной мощности работы передатчика. Подходящий модуль пришлось искать путём перебора разных вариантов, доступных на маркетплейсах, в итоге мне понравился только модуль XL63802. Остальные либо не держали нагрузку, либо отключались из-за малого потребления схемы, когда не шла отправка радиопакета, либо вообще перегорали при первом включении.
Подобрать выключатель питания. Был вариант модуля с кнопкой, чтобы можно было просто вынимать аккумулятор. Поскольку держатель аккумулятора я выбрал такой, чтобы сам аккумулятор было просто не вытащить, обычный хардовый выключатель оказался простым и надёжным решением.
Выбрать модуль для связи по BT, точнее по BLE. Модуль JDY-19 решил эту задачу на ура, при этом потребление тока у него несколько мА — меньше, чем у светодиода, который я поставил сигнализировать о статусе этого модуля.
Расположить модули LoRa и BT с GPS подальше друг от друга, чтобы LoRa-передача попросту не повредила остальные своей работой. С этой проблемой сталкивались в других похожих проектах, и я постарался это учесть.
В схеме нужно немало резисторов, в первой я сам запаял нужные в типоразмере 0.25 Вт. Но как же много места они занимают! Как выяснилось, их в типоразмере, например 0602, могут напаять сразу при производстве платы. Вот только располагать их нужно все на одной стороне — двухсторонняя печать делает процесс намного дороже.
Что касается GPS-модулей, сначала я попробовал NEO 6M. Но, когда сравнил их с NEO 8M, решил брать только последние: они гораздо быстрее находили себя при первом включении.
Найти недорогой быстроразъёмный корпус, в который получится уложить все пять модулей, аккумулятор и антенну для GPS. Такой нашёлся, и под его размер я уже делал последние 10 версий платы.
Как сделать, чтобы трекеры не мешали друг другу передавать данные? Заставить их передавать координаты в разные моменты времени. Время приходит в GPS-данных. Если свободных слотов по времени не осталось, трекеры должны работать на разных каналах. Так можно легко заставить сотню трекеров работать в одной локации при частоте передачи координат каждым трекером раз в 10 секунд.
Что делать, если трекер остался там, где не может установить своё местоположение? Например, если его случайно обронили в какой-то складке местности. В таком случае происходит отправка последнего известного местоположения, но с большим интервалом (скажем, три минуты вместо 10 секунд). Это позволит растянуть время жизни батареи и облегчит поиск того, кто потерялся / что потерялось. Прочёсывать квадрат сто на сто метров проще, чем километр на километр.
Как настроить трекеры? Можно было сделать уникальную прошивку каждому трекеру. Но оказалось, что гораздо удобнее подключить RemoteXY. Можно бесплатно настраивать пять параметров — имя устройства, канал, частоту передачи, время синхронизации, проверить уровень заряда батареи, — чего нам пока хватает. Перейти в режим настройки можно посредством переключения микросвитчей на плате.
Сейчас у меня 12-я версия платы, которую, опять же, можно улучшить. Но она уже позволяет собрать вариант даже лучше того, который я планировал получить.
Проверка работы
Я собрал три таких трекера и два из них, с антеннами разной длины, оставил в лесу на крыше автомобиля. Третий взял с собой. Это был редкий сосновый лес, и в такой местности удалось получать координаты на расстоянии в километр. Трекер с более длинной антенной передавал свои координаты на большее расстояние, но разница оказалась незначительной. Это значит, что бегать можно и с короткой антенной.

Надо сказать, что этот результат оказался лучше тестов с самым первым прототипом. Что могло повлиять:
В лесу в эфире гораздо тише. До этого я проводил тесты на улицах города.
Питание модуля LoRa от 5В вместо 3.5В — 4.2В батареи.
Антенны именно для 433 Мгц.
Так же я попробовал посмотреть передачу сигнала на полностью открытой местности, где два километра оказались не пределом.

Нужен ретранслятор
После первых лесных тестов стало понятно, что от тех, кто носит трекер вблизи от центра соревнований, мы сможем принять сигнал. А что делать с теми, кто ушел от этого центра больше чем на километр? Нужен ретранслятор! И лучше не один. Чтобы он передавал координаты дальше, чем обычный трекер, мы:
дадим ему антенну побольше;
поставим передатчик помощнее;
поднимем его повыше, на верхушку дерева на соседней сопке, или даже привяжем к воздушному шару.
Как сделать, чтобы повторные передачи не мешали самим трекерам? Повторять отправку в другом канале. В центре же соревнований слушать все возможные каналы и объединять поступающую информацию.
Так как ретрансляторы — это тоже портативные устройства, для них в пакете передачи данных предусмотрены поля, где можно дописать идентификатор и уровень разряда батареи. Чтобы в центре заранее увидели, что в соответствующем ретрансляторе пора заменить батареи. Таких поля два. Ведь никто не мешает поставить ретрансляторы в цепочку: им всё равно и они не знают, чей пакет переотправляют — трекера или другого ретранслятора. Всё это определяется только настроенными каналами связи.

Вот такой ретранслятор получился. В приёмнике модуль на 0.5 Вт, в передатчике — на 2 Вт.

Для настройки ретранслятора также использую RemoteXY. Настраивается только канал приёма и канал отправки, также есть индикатор уровня батареи.
Окружаем себя удобными утилитами
В процессе работы над проектом мне были нужны разные инструменты. В итоге пришлось написать несколько простых приложений.
Поначалу я работал с прототипом на Arduino Pro Mini, и его данные можно было считать прямо из COM-порта. Программа на Java с этим справлялась и переотправляла данные в нужном формате в GPS-center, а потом и в собственную систему мониторинга в реальном времени. Но когда я перешёл на использование Arduino Pro Micro и BLE, мне уже не хотелось иметь дел с проводами (например, трекер-приёмник лежал в багажнике или на крыше автомобиля, а я с ноутбуком сидел в салоне). Однако Java-приложение не может читать с BLE. В итоге появилась прокся BLE2COM — она пишет данные с BLE в COM, который через приложение com0com можно считать с другого COM-порта всё тем же Java-приложением.
Также мне нужно было как-то быстро проверять, что протокол трекера корректно поддерживается мобильными клиентами. Чтобы не запускать для этого каждый раз реальный трекер, я сделал эмулятор.
Работа со своей системой мониторинга положения — это очень большие затраты на её поддержку. Я решил перейти на что-то готовое, но с возможностью локальной работы. И тут нам на помощь пришел traccar. Для отображения трекеров в traccar первая утилита была немного переписана — и получилось решение, которое шлёт данные из BLE в traccar.
Настройка этой схемы слежения выглядит так:

Настройка локального слежения за объектами
Использовать такие трекеры можно без доступа к интернету. Для этого нужно уметь запускать все системы локально, в целом достаточно обычного ноутбука. Запуск traccar в локальном Docker подробно описан здесь.
А именно:
Нажимаем Win+R: cmd
И далее в открывшийся терминал вводим:
cd /
mkdir trbase
cd trbase
mkdir traccar
cd traccar
mkdir logs
mkdir conf
mkdir data
docker run --rm --entrypoint cat traccar/traccar:latest /opt/traccar/conf/traccar.xml > conf/traccar.xml
Теперь, если надо, можно отредактировать traccar.xml.
Далее запускаем сам traccar.
docker run --name traccar --hostname traccar --detach --restart unless-stopped --publish 8084:8082 --publish 5000-5150:5000-5150 --publish 5000-5150:5000-5150/udp --volume c:/trbase/traccar/logs/:/opt/traccar/logs/:rw --volume c:/trbase/traccar/conf/:/opt/traccar/conf/:ro --volume c:/trbase/traccar/data/:/opt/traccar/data/:rw traccar/traccar:latest
Открываем http://localhost:8084.
Первый зарегистрировавшийся пользователь становится админом, что нам и нужно.
Указываем логин, почту и пароль, заходим и видим пустую карту и, слева, пустой список устройств. Нажимаем «Добавить», указываем название объекта слежения и идентификатор нашего устройства.

Вот я добавил сразу три трекера, в списке они пока офлайн.

Чтобы получать местоположение трекеров, используем один из них. В моей редакции трекера есть возможность отключить чтение GPS и слушать только LoRa-пакеты. Также очень удобно, что с трекером мы связываемся через BLE: это даёт возможность разместить трекер повыше и там, где удобно. Потому что есть BLE-адаптеры в USB с приличной антенной, что позволяет работать на расстоянии десятков метров.
Для чтения данных с трекера через BLE с компьютера я написал небольшую простую утилиту. Она читает данные BLE (в компактном формате AGLoRa https://github.com/Udj13/AGLoRa/wiki/AGLoRa-BLE-protocol) и отправляет их в traccar под видом одного из поддерживаемых протоколов трекеров (я выбрал starcom, который показался простым и наглядным https://github.com/traccar/traccar/blob/master/src/test/java/org/traccar/protocol/StarcomProtocolDecoderTest.java) по протоколу UDP. У нас traccar запущен локально, поэтому передача будет работать через сеть весьма надёжно.
Запускаем утилиту чтения данных с трекеров через BLE, выбираем в списке устройств нужное, после чего можно дописать в конфиг утилиты идентификатор устройства и его сервиса. Тогда при повторном запуске подключение произойдет автоматически.
На карте начинаем видеть местоположение других трекеров.

Карту для показа местоположения в traccar можно скачать в интернете. Для полной автономности нужно настроить работу traccar с использованием локальных карт.
Настройка использования локальной карты в traccar
Для начала нам нужна сама локальная карта. Самый простой способ её получить — использовать приложение SAS.Planet.
Выбираем в этом приложении тот участок карты, который хотим сделать доступным локально. Сохраняем его в нужной структуре (GlobalMapper Tiles) и с требуемой глубиной детализации в папку, которую будем выдавать локальным веб-сервером. После сохранения файлов карты в папке (там должны появится папки типа z12, z13 и другие подобные, в которых дальше можно найти сами изображения тайлов карты) запускаем локальный веб-сервер на свободном порту. Веб-сервер должен быть настроен на использование CORS. Можно, например, воспользоваться вот таким простым скриптом на Python.
Кладём этот скрипт как файл httpserver.py в корень папки с картами и запускаем. У меня python настроен в WSL, поэтому я захожу в эту папку в WSL и запускаю его там (8095 — порт, на котором поднимется локальный веб-сервер): python -m websrv-cors 8095.
Теперь в traccar указываем Custom Map со следующим адресом сервера: http://localhost:8095/z{z}/{y}/{x}.jpg. И дальше отображается наша карта (должна быть выбрана Custom Map).
Что имеем в итоге
Идея выглядит рабочей, но есть ограничения, некоторые из которых сложно преодолеть.
Сигнал с координатами трекера хорошо распространяется на открытой местности в пределах одного-двух километров.
В плотном лесу расстояние сокращается до 300-500 метров, а в дождь и того меньше. Размещение ретрансляторов может улучшить ситуацию.
Частая передача координат (раз в 10 секунд) быстро разряжает батарею трекера, при такой частоте много трекеров на один канал связи не повесишь. Но для наших дружеских стартов это может быть интересным вариантом слежения.
Комментарии (12)
needsomedata
27.06.2025 13:111) а нужно именно в реалтайме? может достаточно собирать данные черной коробочкой и сдавать оргам?
2) если нужно в реалтайме смотреть за участниками, посмотрите в сторону радио меток - такие были у тиньков марафона — это просто антенна которая считывалась бесконтактно. Фото ниже.
true_alex
27.06.2025 13:11если нужно в реалтайме смотреть за участниками, посмотрите в сторону радио меток - такие были у тиньков марафона — это просто антенна которая считывалась бесконтактно. Фото ниже.
В отличии от спортивного ориентирования участники марафона перемещаются по строго определённому маршруту, где в некоторых точках маршрута можно поставить не маленькие антенны (размером с лист А4 и больше) и так определять примерное местоположение участника.
Организаторы проверяют прохождение дистанции по отметкам на контрольных точках, трек в принципе им не нужен, в качестве отметок ещё встречаются компостеры и картонные карточки, но чаще это электронные системы, коих не одна и не две.
Трек, тем более онлайн, даёт возможность организовать трансляцию.
needsomedata
27.06.2025 13:11и что мешает на контрольных точках считывать данные и передавать по внутренней сети? ну и рисуйте прямые линии на карте между двумя точками
alexhott
27.06.2025 13:11Лора она ведь помехоустойчивая, мешать друг другу они не должны. У нас в доме 1000шт счетчиков , все шлют данные и не особо друг другу мешают. Была вроде тема еще на метровых волнах, та вообще из подвалов работала , а в лесу должна большие расстояния пробивать.
Зы жирный плюс в карму
dpbm Автор
27.06.2025 13:11Они шлют показания не каждые 10 секунд, а гораздо реже
SleepingUp
27.06.2025 13:11Ну и это скорее всего Lorawan, там 7 каналов на шлюзе, плюс разный "спрединг фактор" может быть на самих устройствах, это позволяет нескольким одновременно на одной частоте быть услышанными. Плюс в самом модуле есть настроечка "слушать эфир перед передачей". Магия там конечно есть, но умеренная. Но тащить Lorawan в лес это дорого, сложно и ненужно )
VO_Obsidian
27.06.2025 13:11По опыту скажу что тащить аппаратно это дешево и легко, самое дорогое это шлюз от какого-ниубдь Heltec тысяч за 7-10 и малинка для Chrpstack. Другой вопрос в портировании стека оконечного устройства, если не брать устаревший LMIC, а современный SWL2001 то пара месяцев совокупления для стабильной работы гарантировано.
x89377
27.06.2025 13:11Немного по-меньше
SleepingUp
Павел, у тебя получилась очень крутая и полезная статья!!!
Я тот самый Евгений на которого есть ссылки и я просто хотел добавить что у нас есть небольшой чатик в телеге где мы обсуждаем трекеры и проблемы при сборке.
Не хочется светить публичной ссылкой чтобы потом не вычищать спамеров, но если вам это интересно то напишите Павлу или мне в личку свое имя, мы вас в него добавим.