Приёмник Teltonika open_teltonika_gps_tracker
Назначение и канонический контракт
Обработчик запускает пример UDP-приёмника AVL-пакетов:
получает датаграмму и разбирает её;
пишет читаемую диагностику;
при включённых режимах записывает GPX и отдельные AVL-файлы;
отправляет ответ устройству.
Координаты не записываются этим путём в Orders/Provider/Ticket; интеграция с картой и смена статуса заказа здесь не выполняются.
В Blockly зафиксирована typed operation teltonika_udp_receiver. Сгенерированный Python вызывает binding; runtime сверяет точную program tuple с каталогом и загружает first_party_operations/open_teltonika_gps_tracker.py. Бизнес-детали находятся также в catcher/decoder/GPX recorder, поэтому они включены в источники сценария. Совпадение generated wrapper не заменяет анализа вложенной operation.
BPMN описательные, isExecutable=false; исполняется Python из Blockly, а не JSON/XML Wiki. Сценарий описывает текущий пример, не обещает поддержку всех вариантов протокола Teltonika.
Запуск и UDP loop (BPMN)
Схема BPMN Вписать − + На весь экран Скачать исходник Скачать SVG
Загрузка схемы…
Исходник схемы <?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_teltonika_startup" targetNamespace="urn:sharix:knowledge:handlers">
<bpmn:process id="udp_Process_udp" name="open_teltonika_gps_tracker: XMPP bootstrap и UDP loop" isExecutable="false">
<bpmn:documentation>{"notes": ["BPMN isExecutable=false; typed operation teltonika_udp_receiver из Blockly, Python сверён канонически.", "Штатный binding requires_xmpp=True: UDP запускается после XMPP connection preflight.", "GPX и отдельные AVL файлы по умолчанию выключены в этом binding; интерактивный catcher main не вызывается.", "ACK из raw byte slices не доказывает успешное сохранение всех точек."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker.py", "repository": "sharix-open-handlers-examples", "sha256": "176dc8e04c8370481da568124f7e5a27a5418592a3947f718986b042b4a5e083"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_teltonika_gps_tracker.json", "repository": "sharix-open-handlers-examples", "sha256": "a44f034cf10fe311ba6775c8c3579bd14448dc95c9c8ef08fa699c5c2b13ef2d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "first_party_operations/open_teltonika_gps_tracker.py", "repository": "sharix-open-handlers-examples", "sha256": "d8c766ceecb6eabdd24bccc0d0f6e9ddcab1fc3b8dab7432b1cf6a0dbda27e86"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "config.py", "repository": "sharix-open-handlers-examples", "sha256": "7b23db9ed283d3bbc3cf2cfbd5d41c629f6be507c3ca38c611572d08a75743a4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "first_party_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "7f4dc6607ad62f3150c58de6341b758ebe97f81bd936c9ec033b7d86fed44640"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/first_party_handler_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "fb5ee98561b029de9291e73c2a08205cc9fc2b7b239abffe4a4bb24f56093bdb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "main.py", "repository": "sharix-open-handlers-backend", "sha256": "66b7df94fedbec931ed4cb2d4e1afd9cf0386e14ed0932e22b15eb301cd792d7"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "runtime_provider.py", "repository": "sharix-open-handlers-backend", "sha256": "c311d3b0721d18d8eccc9cd7fba155108bf285df3002507ee915ee73b797a2f4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/JabberBot.py", "repository": "sharix-open-handlers-backend", "sha256": "7fbd4d1f41bc867109b73dbb632efcfae920269a1aaf6da0e577cc70838820f1"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "teltonika_config.py", "repository": "sharix-open-handlers-examples", "sha256": "37b1abca5f520f89812e0c0f02c0386511a69553ace5e9cf29243d0ad3d7fb0d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/catcher.py", "repository": "sharix-open-handlers-examples", "sha256": "f99e418651e38d15bf198e5cd8fb547d97fc084a7bd330e88f9bb9a8e0cdf6dd"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/decoder.py", "repository": "sharix-open-handlers-examples", "sha256": "e5420416a997acfabf29ae0942d8fa95b52890cec71d036f39d9164c210942d3"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/gpx_recorder.py", "repository": "sharix-open-handlers-examples", "sha256": "fa7cbabbfe354fade58e2d9b16195df911755dc49489c405fad389a38abb1b38"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/config_importer.py", "repository": "sharix-open-handlers-examples", "sha256": "3b2ca95e371bdf92dad65a7a9bd4befd0682f0c8ea03212c94b1c2678376c5df"}]}</bpmn:documentation>
<bpmn:laneSet id="udp_Lanes_udp">
<bpmn:lane id="udp_Lane_worker" name="Выбранный Python binding, не отдельный запуск catcher.main">
<bpmn:flowNodeRef>udp_start</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_xmpp</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_socket</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_stop</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_close</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_receive</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_result</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_repeat</bpmn:flowNodeRef>
<bpmn:flowNodeRef>udp_error</bpmn:flowNodeRef>
</bpmn:lane>
</bpmn:laneSet>
<bpmn:startEvent id="udp_start" name="Штатный launcher, typed binding">
<bpmn:outgoing>udp_Flow_0</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:serviceTask id="udp_xmpp" name="XMPP connect preflight; callback и supervisor">
<bpmn:incoming>udp_Flow_0</bpmn:incoming>
<bpmn:outgoing>udp_Flow_1</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:serviceTask id="udp_socket" name="AF_INET/SOCK_DGRAM, reuseaddr, timeout=1s, bind env host/port">
<bpmn:incoming>udp_Flow_1</bpmn:incoming>
<bpmn:outgoing>udp_Flow_2</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="udp_stop" name="exit_event установлен?">
<bpmn:incoming>udp_Flow_2</bpmn:incoming>
<bpmn:outgoing>udp_Flow_3</bpmn:outgoing>
<bpmn:outgoing>udp_Flow_4</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:endEvent id="udp_close" name="Да: finally закрывает socket, затем XMPP">
<bpmn:incoming>udp_Flow_3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:serviceTask id="udp_receive" name="receive_and_print: recvfrom(1024), parse, optional write, ACK">
<bpmn:incoming>udp_Flow_4</bpmn:incoming>
<bpmn:outgoing>udp_Flow_5</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="udp_result" name="Чем закончился вызов?">
<bpmn:incoming>udp_Flow_5</bpmn:incoming>
<bpmn:outgoing>udp_Flow_6</bpmn:outgoing>
<bpmn:outgoing>udp_Flow_7</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:endEvent id="udp_repeat" name="Успех/обычный timeout: следующий проход loop">
<bpmn:incoming>udp_Flow_6</bpmn:incoming>
</bpmn:endEvent>
<bpmn:endEvent id="udp_error" name="Иное исключение: socket finally close; общий restart policy">
<bpmn:incoming>udp_Flow_7</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="udp_Flow_0" sourceRef="udp_start" targetRef="udp_xmpp" name="" />
<bpmn:sequenceFlow id="udp_Flow_1" sourceRef="udp_xmpp" targetRef="udp_socket" name="" />
<bpmn:sequenceFlow id="udp_Flow_2" sourceRef="udp_socket" targetRef="udp_stop" name="" />
<bpmn:sequenceFlow id="udp_Flow_3" sourceRef="udp_stop" targetRef="udp_close" name="Да" />
<bpmn:sequenceFlow id="udp_Flow_4" sourceRef="udp_stop" targetRef="udp_receive" name="Нет" />
<bpmn:sequenceFlow id="udp_Flow_5" sourceRef="udp_receive" targetRef="udp_result" name="" />
<bpmn:sequenceFlow id="udp_Flow_6" sourceRef="udp_result" targetRef="udp_repeat" name="Возврат / timeout" />
<bpmn:sequenceFlow id="udp_Flow_7" sourceRef="udp_result" targetRef="udp_error" name="Иное исключение" />
</bpmn:process>
<bpmn:collaboration id="Collaboration_teltonika_startup">
<bpmn:participant id="udp_Pool_udp" name="open_teltonika_gps_tracker: XMPP bootstrap и UDP loop" processRef="udp_Process_udp" />
<bpmn:participant id="device_Participant" name="GPS-устройство: UDP датаграммы к настроенному endpoint" />
<bpmn:messageFlow id="Message_teltonika_startup_0" sourceRef="device_Participant" targetRef="udp_receive" name="UDP трафик отделён от XMPP; готовность XMPP не доказывает приход UDP" />
</bpmn:collaboration>
<bpmndi:BPMNDiagram id="Diagram_teltonika_startup">
<bpmndi:BPMNPlane id="Plane_teltonika_startup" bpmnElement="Collaboration_teltonika_startup">
<bpmndi:BPMNShape id="udp_DI_Pool_udp" bpmnElement="udp_Pool_udp" isHorizontal="true">
<dc:Bounds x="0.0" y="0.0" width="2150" height="440" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_Lane_worker" bpmnElement="udp_Lane_worker" isHorizontal="true">
<dc:Bounds x="30.0" y="0.0" width="2120" height="440" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_start" bpmnElement="udp_start">
<dc:Bounds x="132.0" y="82.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_xmpp" bpmnElement="udp_xmpp">
<dc:Bounds x="365.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_socket" bpmnElement="udp_socket">
<dc:Bounds x="675.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_stop" bpmnElement="udp_stop">
<dc:Bounds x="1035.0" y="75.0" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_close" bpmnElement="udp_close">
<dc:Bounds x="1042.0" y="322.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_receive" bpmnElement="udp_receive">
<dc:Bounds x="1295.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_result" bpmnElement="udp_result">
<dc:Bounds x="1655.0" y="75.0" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_repeat" bpmnElement="udp_repeat">
<dc:Bounds x="1972.0" y="82.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="udp_DI_error" bpmnElement="udp_error">
<dc:Bounds x="1662.0" y="322.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="udp_DI_Flow_0" bpmnElement="udp_Flow_0">
<di:waypoint x="168.0" y="100.0" />
<di:waypoint x="365.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_1" bpmnElement="udp_Flow_1">
<di:waypoint x="515.0" y="100.0" />
<di:waypoint x="675.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_2" bpmnElement="udp_Flow_2">
<di:waypoint x="825.0" y="100.0" />
<di:waypoint x="1035.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_3" bpmnElement="udp_Flow_3">
<di:waypoint x="1060.0" y="125.0" />
<di:waypoint x="1060.0" y="322.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_4" bpmnElement="udp_Flow_4">
<di:waypoint x="1085.0" y="100.0" />
<di:waypoint x="1295.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_5" bpmnElement="udp_Flow_5">
<di:waypoint x="1445.0" y="100.0" />
<di:waypoint x="1655.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_6" bpmnElement="udp_Flow_6">
<di:waypoint x="1705.0" y="100.0" />
<di:waypoint x="1972.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="udp_DI_Flow_7" bpmnElement="udp_Flow_7">
<di:waypoint x="1680.0" y="125.0" />
<di:waypoint x="1680.0" y="322.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="DI_device_Participant" bpmnElement="device_Participant" isHorizontal="true">
<dc:Bounds x="0" y="650" width="2150" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="DI_Message_teltonika_startup_0" bpmnElement="Message_teltonika_startup_0">
<di:waypoint x="1800" y="650" />
<di:waypoint x="2080" y="650" />
<di:waypoint x="2080" y="30" />
<di:waypoint x="1370" y="30" />
<di:waypoint x="1370" y="65" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1550" y="530" width="260" height="42" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions> Для просмотра схемы включите JavaScript. Исходник доступен выше.
Несмотря на UDP-полезную работу, текущий binding имеет requires_xmpp=true и создаёт JabberBot. Общий launcher сначала подключает XMPP, регистрирует callback/supervisor и ждёт connection preflight. При неуспехе UDP loop не начинается. Успешный XMPP connect, напротив, ещё не доказывает доступность UDP endpoint устройству.
UDP loop после XMPP bootstrap:
Создать IPv4 UDP socket с SO_REUSEADDR.
Установить timeout=1.0 секунды и bind на TELTONIKA_HOSTNAME/TELTONIKA_PORT.
Пока exit_event не установлен — вызывать receive_and_print.
При TimeoutError/socket.timeout продолжать цикл.
При другом исключении выйти через finally с закрытием socket; далее действует общая политика launcher.
При штатной остановке exit_event проверяется между вызовами; затем закрываются socket и XMPP.
В operation нет отдельного TCP listener или IMEI handshake. Закомментированный TCP-код в catcher не является активным путём запуска.
Одна датаграмма: разбор, файлы и ACK (BPMN)
Схема BPMN Вписать − + На весь экран Скачать исходник Скачать SVG
Загрузка схемы…
Исходник схемы <?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_teltonika_packet" targetNamespace="urn:sharix:knowledge:handlers">
<bpmn:process id="packet_Process_packet" name="Одна датаграмма: decoder, условные файлы и ответ устройству" isExecutable="false">
<bpmn:documentation>{"notes": ["BPMN isExecutable=false; typed operation teltonika_udp_receiver из Blockly, Python сверён канонически.", "Штатный binding requires_xmpp=True: UDP запускается после XMPP connection preflight.", "GPX и отдельные AVL файлы по умолчанию выключены в этом binding; интерактивный catcher main не вызывается.", "ACK из raw byte slices не доказывает успешное сохранение всех точек."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker.py", "repository": "sharix-open-handlers-examples", "sha256": "176dc8e04c8370481da568124f7e5a27a5418592a3947f718986b042b4a5e083"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_teltonika_gps_tracker.json", "repository": "sharix-open-handlers-examples", "sha256": "a44f034cf10fe311ba6775c8c3579bd14448dc95c9c8ef08fa699c5c2b13ef2d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "first_party_operations/open_teltonika_gps_tracker.py", "repository": "sharix-open-handlers-examples", "sha256": "d8c766ceecb6eabdd24bccc0d0f6e9ddcab1fc3b8dab7432b1cf6a0dbda27e86"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "config.py", "repository": "sharix-open-handlers-examples", "sha256": "7b23db9ed283d3bbc3cf2cfbd5d41c629f6be507c3ca38c611572d08a75743a4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "first_party_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "7f4dc6607ad62f3150c58de6341b758ebe97f81bd936c9ec033b7d86fed44640"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/first_party_handler_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "fb5ee98561b029de9291e73c2a08205cc9fc2b7b239abffe4a4bb24f56093bdb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "main.py", "repository": "sharix-open-handlers-backend", "sha256": "66b7df94fedbec931ed4cb2d4e1afd9cf0386e14ed0932e22b15eb301cd792d7"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "runtime_provider.py", "repository": "sharix-open-handlers-backend", "sha256": "c311d3b0721d18d8eccc9cd7fba155108bf285df3002507ee915ee73b797a2f4"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/JabberBot.py", "repository": "sharix-open-handlers-backend", "sha256": "7fbd4d1f41bc867109b73dbb632efcfae920269a1aaf6da0e577cc70838820f1"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "teltonika_config.py", "repository": "sharix-open-handlers-examples", "sha256": "37b1abca5f520f89812e0c0f02c0386511a69553ace5e9cf29243d0ad3d7fb0d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/catcher.py", "repository": "sharix-open-handlers-examples", "sha256": "f99e418651e38d15bf198e5cd8fb547d97fc084a7bd330e88f9bb9a8e0cdf6dd"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/decoder.py", "repository": "sharix-open-handlers-examples", "sha256": "e5420416a997acfabf29ae0942d8fa95b52890cec71d036f39d9164c210942d3"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/gpx_recorder.py", "repository": "sharix-open-handlers-examples", "sha256": "fa7cbabbfe354fade58e2d9b16195df911755dc49489c405fad389a38abb1b38"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_teltonika_gps_tracker_dir/config_importer.py", "repository": "sharix-open-handlers-examples", "sha256": "3b2ca95e371bdf92dad65a7a9bd4befd0682f0c8ea03212c94b1c2678376c5df"}]}</bpmn:documentation>
<bpmn:laneSet id="packet_Lanes_packet">
<bpmn:lane id="packet_Lane_worker" name="Без Ticket/Orders/Provider CRUD в этом пути">
<bpmn:flowNodeRef>packet_start</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_parse</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_parsed</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_log</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_record</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_gpx</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_ack</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_end</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_broken</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_error</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_abort</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_gpx_error</bpmn:flowNodeRef>
<bpmn:flowNodeRef>packet_ack_error</bpmn:flowNodeRef>
</bpmn:lane>
</bpmn:laneSet>
<bpmn:startEvent id="packet_start" name="recvfrom: raw data + sender addr">
<bpmn:outgoing>packet_Flow_0</bpmn:outgoing>
<bpmn:messageEventDefinition />
</bpmn:startEvent>
<bpmn:serviceTask id="packet_parse" name="update_data; parse length/header/IMEI/records/IO">
<bpmn:incoming>packet_Flow_0</bpmn:incoming>
<bpmn:outgoing>packet_Flow_1</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="packet_parsed" name="parse вернул структуру?">
<bpmn:incoming>packet_Flow_1</bpmn:incoming>
<bpmn:outgoing>packet_Flow_2</bpmn:outgoing>
<bpmn:outgoing>packet_Flow_8</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="packet_log" name="Читаемый logging; отдельный AVL log лишь при write_logs">
<bpmn:incoming>packet_Flow_2</bpmn:incoming>
<bpmn:outgoing>packet_Flow_3</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:exclusiveGateway id="packet_record" name="GPX recorder включён?">
<bpmn:incoming>packet_Flow_3</bpmn:incoming>
<bpmn:outgoing>packet_Flow_4</bpmn:outgoing>
<bpmn:outgoing>packet_Flow_6</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:serviceTask id="packet_gpx" name="Добавить точки по IMEI, пропустить (0,0)">
<bpmn:incoming>packet_Flow_4</bpmn:incoming>
<bpmn:outgoing>packet_Flow_5</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:sendTask id="packet_ack" name="answer_to_device из raw slices; sendto(sender addr)">
<bpmn:incoming>packet_Flow_5</bpmn:incoming>
<bpmn:incoming>packet_Flow_6</bpmn:incoming>
<bpmn:incoming>packet_Flow_9</bpmn:incoming>
<bpmn:outgoing>packet_Flow_7</bpmn:outgoing>
</bpmn:sendTask>
<bpmn:endEvent id="packet_end" name="Следующая датаграмма; бизнес-объект не обновлён">
<bpmn:incoming>packet_Flow_7</bpmn:incoming>
</bpmn:endEvent>
<bpmn:serviceTask id="packet_broken" name="BROKEN DATA / parse None; GPX не пишется">
<bpmn:incoming>packet_Flow_8</bpmn:incoming>
<bpmn:outgoing>packet_Flow_9</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:boundaryEvent id="packet_error" name="Parse / AVL file исключение" attachedToRef="packet_parse" cancelActivity="true">
<bpmn:outgoing>packet_Flow_10</bpmn:outgoing>
<bpmn:errorEventDefinition />
</bpmn:boundaryEvent>
<bpmn:endEvent id="packet_abort" name="Нет нормального ACK; внешний loop завершится с ошибкой">
<bpmn:incoming>packet_Flow_10</bpmn:incoming>
<bpmn:incoming>packet_Flow_11</bpmn:incoming>
<bpmn:incoming>packet_Flow_12</bpmn:incoming>
</bpmn:endEvent>
<bpmn:boundaryEvent id="packet_gpx_error" name="GPX file исключение" attachedToRef="packet_gpx" cancelActivity="true">
<bpmn:outgoing>packet_Flow_11</bpmn:outgoing>
<bpmn:errorEventDefinition />
</bpmn:boundaryEvent>
<bpmn:boundaryEvent id="packet_ack_error" name="sendto исключение" attachedToRef="packet_ack" cancelActivity="true">
<bpmn:outgoing>packet_Flow_12</bpmn:outgoing>
<bpmn:errorEventDefinition />
</bpmn:boundaryEvent>
<bpmn:sequenceFlow id="packet_Flow_0" sourceRef="packet_start" targetRef="packet_parse" name="" />
<bpmn:sequenceFlow id="packet_Flow_1" sourceRef="packet_parse" targetRef="packet_parsed" name="" />
<bpmn:sequenceFlow id="packet_Flow_2" sourceRef="packet_parsed" targetRef="packet_log" name="Да" />
<bpmn:sequenceFlow id="packet_Flow_3" sourceRef="packet_log" targetRef="packet_record" name="" />
<bpmn:sequenceFlow id="packet_Flow_4" sourceRef="packet_record" targetRef="packet_gpx" name="Да" />
<bpmn:sequenceFlow id="packet_Flow_5" sourceRef="packet_gpx" targetRef="packet_ack" name="" />
<bpmn:sequenceFlow id="packet_Flow_6" sourceRef="packet_record" targetRef="packet_ack" name="Нет" />
<bpmn:sequenceFlow id="packet_Flow_7" sourceRef="packet_ack" targetRef="packet_end" name="" />
<bpmn:sequenceFlow id="packet_Flow_8" sourceRef="packet_parsed" targetRef="packet_broken" name="Нет" />
<bpmn:sequenceFlow id="packet_Flow_9" sourceRef="packet_broken" targetRef="packet_ack" name="" />
<bpmn:sequenceFlow id="packet_Flow_10" sourceRef="packet_error" targetRef="packet_abort" name="" />
<bpmn:sequenceFlow id="packet_Flow_11" sourceRef="packet_gpx_error" targetRef="packet_abort" name="" />
<bpmn:sequenceFlow id="packet_Flow_12" sourceRef="packet_ack_error" targetRef="packet_abort" name="" />
</bpmn:process>
<bpmn:collaboration id="Collaboration_teltonika_packet">
<bpmn:participant id="packet_Pool_packet" name="Одна датаграмма: decoder, условные файлы и ответ устройству" processRef="packet_Process_packet" />
<bpmn:participant id="device_Participant" name="UDP-устройство: ACK транспортного примера, не receipt БД/GPX" />
<bpmn:messageFlow id="Message_teltonika_packet_0" sourceRef="packet_ack" targetRef="device_Participant" name="packet ids и count извлечены из raw bytes, не из фактически сохранённых точек" />
</bpmn:collaboration>
<bpmndi:BPMNDiagram id="Diagram_teltonika_packet">
<bpmndi:BPMNPlane id="Plane_teltonika_packet" bpmnElement="Collaboration_teltonika_packet">
<bpmndi:BPMNShape id="packet_DI_Pool_packet" bpmnElement="packet_Pool_packet" isHorizontal="true">
<dc:Bounds x="0.0" y="0.0" width="2150" height="680" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_Lane_worker" bpmnElement="packet_Lane_worker" isHorizontal="true">
<dc:Bounds x="30.0" y="0.0" width="2120" height="680" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_start" bpmnElement="packet_start">
<dc:Bounds x="132.0" y="82.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_parse" bpmnElement="packet_parse">
<dc:Bounds x="365.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_parsed" bpmnElement="packet_parsed">
<dc:Bounds x="725.0" y="75.0" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_log" bpmnElement="packet_log">
<dc:Bounds x="985.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_record" bpmnElement="packet_record">
<dc:Bounds x="1345.0" y="75.0" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_gpx" bpmnElement="packet_gpx">
<dc:Bounds x="1605.0" y="65.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_ack" bpmnElement="packet_ack">
<dc:Bounds x="1605.0" y="305.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_end" bpmnElement="packet_end">
<dc:Bounds x="1972.0" y="322.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_broken" bpmnElement="packet_broken">
<dc:Bounds x="675.0" y="545.0" width="150" height="70" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_error" bpmnElement="packet_error">
<dc:Bounds x="472.0" y="117.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_abort" bpmnElement="packet_abort">
<dc:Bounds x="422.0" y="562.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_gpx_error" bpmnElement="packet_gpx_error">
<dc:Bounds x="1712.0" y="117.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="packet_DI_ack_error" bpmnElement="packet_ack_error">
<dc:Bounds x="1712.0" y="357.0" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="packet_DI_Flow_0" bpmnElement="packet_Flow_0">
<di:waypoint x="168.0" y="100.0" />
<di:waypoint x="365.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_1" bpmnElement="packet_Flow_1">
<di:waypoint x="515.0" y="100.0" />
<di:waypoint x="725.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_2" bpmnElement="packet_Flow_2">
<di:waypoint x="775.0" y="100.0" />
<di:waypoint x="985.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_3" bpmnElement="packet_Flow_3">
<di:waypoint x="1135.0" y="100.0" />
<di:waypoint x="1345.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_4" bpmnElement="packet_Flow_4">
<di:waypoint x="1395.0" y="100.0" />
<di:waypoint x="1605.0" y="100.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_5" bpmnElement="packet_Flow_5">
<di:waypoint x="1680.0" y="135.0" />
<di:waypoint x="1680.0" y="305.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_6" bpmnElement="packet_Flow_6">
<di:waypoint x="1395.0" y="100.0" />
<di:waypoint x="1490.0" y="100.0" />
<di:waypoint x="1550.0" y="100.0" />
<di:waypoint x="1550.0" y="270.0" />
<di:waypoint x="1680.0" y="270.0" />
<di:waypoint x="1680.0" y="305.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_7" bpmnElement="packet_Flow_7">
<di:waypoint x="1755.0" y="340.0" />
<di:waypoint x="1972.0" y="340.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_8" bpmnElement="packet_Flow_8">
<di:waypoint x="750.0" y="125.0" />
<di:waypoint x="750.0" y="545.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_9" bpmnElement="packet_Flow_9">
<di:waypoint x="825.0" y="580.0" />
<di:waypoint x="870.0" y="580.0" />
<di:waypoint x="1100.0" y="580.0" />
<di:waypoint x="1100.0" y="270.0" />
<di:waypoint x="1680.0" y="270.0" />
<di:waypoint x="1680.0" y="305.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_10" bpmnElement="packet_Flow_10">
<di:waypoint x="508.0" y="135.0" />
<di:waypoint x="550.0" y="135.0" />
<di:waypoint x="600.0" y="135.0" />
<di:waypoint x="600.0" y="510.0" />
<di:waypoint x="440.0" y="510.0" />
<di:waypoint x="440.0" y="562.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_11" bpmnElement="packet_Flow_11">
<di:waypoint x="1748.0" y="135.0" />
<di:waypoint x="1790.0" y="135.0" />
<di:waypoint x="1830.0" y="135.0" />
<di:waypoint x="1830.0" y="630.0" />
<di:waypoint x="440.0" y="630.0" />
<di:waypoint x="440.0" y="562.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="packet_DI_Flow_12" bpmnElement="packet_Flow_12">
<di:waypoint x="1748.0" y="375.0" />
<di:waypoint x="1790.0" y="375.0" />
<di:waypoint x="1830.0" y="375.0" />
<di:waypoint x="1830.0" y="630.0" />
<di:waypoint x="440.0" y="630.0" />
<di:waypoint x="440.0" y="562.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="DI_device_Participant" bpmnElement="device_Participant" isHorizontal="true">
<dc:Bounds x="0" y="900" width="2150" height="130" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="DI_Message_teltonika_packet_0" bpmnElement="Message_teltonika_packet_0">
<di:waypoint x="1680" y="375" />
<di:waypoint x="1680" y="800" />
<di:waypoint x="1100" y="800" />
<di:waypoint x="1100" y="900" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1160" y="755" width="260" height="42" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions> Для просмотра схемы включите JavaScript. Исходник доступен выше.
Обработка одной датаграммы:
Получить до 1024 байт через recvfrom и адрес отправителя.
Передать raw bytes и addr decoder.
Проверить заявленную/фактическую длину, извлечь заголовки, IMEI, codec, records и IO.
При успешной структуре сформировать читаемый logging-output.
Отдельный AVL-файл писать только при write_logs=true.
После parse:
Если есть структура и GPX recorder включён — добавить точки с координатами, высотой и timestamp по IMEI.
Пропустить точку (0,0).
Сформировать ACK через answer_to_device.
Вызвать sendto на адрес источника датаграммы.
ACK формируется и после parse_data=None, если до него не было исключения.
ACK не равен сохранённой телеметрии
ACK берёт поля непосредственно из raw bytes:
Count не вычисляется по фактически разобранным или записанным GPX-точкам. Получение ACK не подтверждает сохранённую телеметрию или обновление бизнес-объекта.
Поэтому ACK не доказывает корректность всех координат, запись файла или обновление бизнес-объекта. Исключение декодирования, файловой операции или sendto — другой исход: оно не обрабатывается как обычный socket timeout и может завершить текущий запуск с последующим restart. Разбор не содержит полноценного fail-closed валидатора всех возможных форматов/codec; IMEI извлекается как данные, а не сопоставляется здесь с разрешённым устройством в БД.
Лимит recvfrom — 1024 байта. Для диагностики длинных/повреждённых пакетов учитывайте этот предел и реальный формат входа, а не только факт получения UDP. Сценарий не объявляет универсальную совместимость по одному удачно разобранному пакету.
Что действительно включено при штатном запуске
В штатном first-party запуске:
GPX_Recorder создаётся с is_recording=false;
AVL_DATA — с write_logs=false и show_broken_data=false;
binding вызывает receive_and_print напрямую;
catcher.main, control_thread и переключатели записи этим путём не вызываются.
Команды stdin g/l/b/q самостоятельного примера не являются интерфейсом управления handler через XMPP или launcher.
Обычный читаемый logging при удачном parse выполняется, но отдельные AVL-файлы и GPX в этом binding автоматически не включаются. Директории могут создаваться при импорте recorder/decoder ещё до открытия socket; наличие каталога не доказывает активную запись. Если запись включена другим разрешённым способом, GPX хранится по IMEI и времени первой точки, AVL logs — по IMEI в своих output dirs. Это файлы примера, а не проекция в БД сервиса.
Настройки и диагностика
Назначение Настройка / значение источника
UDP host TELTONIKA_HOSTNAME; default 0.0.0.0
UDP port TELTONIKA_PORT; default 350, допустимо 1..65535
Часовой пояс timestamp TELTONIKA_TIMEZONE; default UTC, проверяется ZoneInfo
Каталог отдельного AVL-log TELTONIKA_AVL_OUTPUT_DIR
Каталог GPX TELTONIKA_GPX_OUTPUT_DIR
Период проверки остановки socket loop Socket timeout 1.0 секунды, в operation
Подключение и общие restart limits Штатные настройки общего handler runtime
Относительные output paths разрешаются от корня проекта; реальные значения и managed permissions определяет установка. Не следует считать default внутри каталога примера доказательством фактического пути production. Проверяйте штатную env/permission-подготовку, не создавая параллельный неуправляемый конфиг для handler.
Порядок диагностики:
Сверить выбранные Python version и binding.
Проверить XMPP preflight: без него UDP loop не начинается.
Проверить import и права output dirs, затем bind UDP.
Проверить приход датаграммы и реальный parse result.
Отдельно проверить флаги записи, созданные данные и ACK.
XMPP callback только логирует допустимые chat/normal от технического allowlist; он не переключает GPX и не обновляет трекер в БД.
Проверенные источники
Git SHA/SHA-256 и модели закреплены в metadata/BPMN; упаковка повторно сверяет файлы. Handler, socket, устройства и тестовые сообщения при анализе не запускались, секретные runtime env не читались. Общий автоматический hook Wiki пока не завершён.
Связанные материалы