-
Для создания mqtt клиента используйте
MQTTClient(на базе paho) из библиотеки wb_common. Вы можете использовать функцию клиента start(), которая по умолчанию запускает клиента в отдельном потоке. Также вы можете выключить создание отдельного потока и вручную запускать клиента через start() + loop_forever() в текущем потоке. Использовать функцию loop() для работы не рекомендуется, тк она не делает автоматический реконнект в случае разрыва соединения с брокером. -
Для перехвата сигналов используйте библиотеку signal: signal.SIGTERM (остановка через systemctl stop) и signal.SIGINT (остановка через Ctrl-C в консоли). В обработчике сигнала нужно вызвать stop(). Если вы используете loop_forever(), то в обработчике не нужно принудительно завершать основной процесс, выполнение после обработки сигнала вернётся в loop_forever(), которая завершится. Больше информации и примеров http://www.steves-internet-guide.com/client-connections-python-mqtt/.
-
Запуск. Как правило, весь основной код оформляется одельным python-пакетом. В пакете создается основной файл (например
main.pyили по имени сервиса). В нем создается функцияmain, которая может быть как импортирована в другой код, так и запущена при обычном запуске файла из консоли. В папке/bin/создается файл, который будет импортировать и запускатьmainиз пакета.
Исходная система - где происходит сборка deb-пакета. В терминологии debian - build-система Целевая система - куда устанавливается пакет. В терминологии debian - host-система
Для сборки deb-пакетов в Wiren Board используется кросс-компиляция. Это значит, что сборка будет происходить на машине с архитектурой, отличной от той, на которой всё будет запускаться, и нужно подсказать сборщику, как правильно разрешать зависимости.
-
Собрать пакет вручную и посмотреть что получается можно внутри devcontainer-a командой
dpkg-buildpackage -rfakeroot -us -ucДиректория debian в проекте (исходная система) будет содержать структуру директорий относительно корня целевой системы. Перед сборкой не забыть установить build-depends.
-
/debian/control для Python
Для source пакета в
Build-Dependsнужно использоватьpython3-allвместоpython3, потому что это отвязывает процедуру сборки от конкретной реализации Python, иdistutilsавтоматически подтягивается с подходящей версией. Писатьpython3-all:anyв пакетах-библиотеках обычно не имеет смысла, тк используемarch-all.Source: wb-my-lib ... Build-Depends: python3-all, dh-python, ...Для binary пакетов
Package: wb-my-lib Architecture: all Depends: ${python3:Depends}, ${misc:Depends}, ...Architecture: all(не путать сArchitecture: any) нужен для того, чтобы собранный пакет был платформо-независимый.python3в зависимости не записывается, его заменяет${python3:Depends}. -
Кодогенерация при кросс-компиляции
У нас этот сценарий применяется в wb-mqtt-serial. Кодогенерация там - сборка шаблонов с помощью
j2cli. Для того чтобы установитьj2cli, совместимый с архитектурой сборщика, используем:native.Source: wb-mqtt-serial ... Build-Depends: ..., j2cli:native -
Резервное копирование конфигов
Сервис wb-configs-early умеет делать резервное копирование файлов перед началом работы системы и перед выключением. Он перемещает сам файл конфига в раздел, который не сбрасывается при установке обновлений, а сам конфиг в исходном расположении
/etc/заменяет на симлинк. Для этого нужно в папку/etc/wb-configs.dположить скрипт, который вызоветwb_moveдля всех нужных конфигов (в данном примере это10wb-python-service-template).
-
Почему all-пакеты не собираются в sbuild с
--host=armhf?Альтернативная формулировка - почему all-пакеты нельзя было раньше собрать через
wbdev cdeb.Во-первых, потому что в Debian обычно делят сборку all-пакетов и кросс-компиляцию, вот (пруф).
Во-вторых, это могло бы заработать, если бы мейнтейнеры Python-библиотек в Debian озадачивались добавлением
Multi-Arch: foreignв свои пакеты. На ноябрь 2022 этой пометки нет как минимум вpython3-paho-mqttиpython3-jinja2, а эти пакеты мы часто используем.В итоге оказалось проще пойти каноничным путём и собирать
allиanyотдельно. -
Для чего при сборке cdeb запускаются и
--arch-all, и--arch-any?Раньше для сборки пакетов отдельно использовались
wbdev cdeb(дляany) иwbdev ndeb(дляall). Это было очень актуально во временаwheezy, когда не было ещё multiarch, и пакеты для Wiren Board приходилось собирать в chroot с qemu. Тогда для экономии времени сборки (qemu медленный) сделали отдельно командуndeb, которой собиралиall-пакеты прямо в Docker-окружении.Потом мы перешли на sbuild, и разница между
cdebиndebстала размываться, потому что для обеих команд уже использовалось sbuild-окружение, только с разным аргументом--host.Так получилось, что при переходе на релизную систему, когда для сборки стало нужно указывать, для какой платформы происходит сборка (wb5/wb6/wb7), добавление наших репозиториев (
http://deb.wirenboard.com/wbX/<deb-release>) делалось только вcdeb. Дляndebпоявился репозиторийdev-tools, который нужен скорее для сборки пакетов, нужных нам на производстве и для CI.Пока наши all-пакеты не зависели друг от друга при сборке, можно было продолжать пользоваться такой системой, выбирая в зависимости от типа пакета
cdebилиndeb. При разработке wb-device-manager нам понадобились all-зависимости из нашего репозитория.В этот момент @webconn решил, что пора объединять
cdebиndeb- так получается меньше пайплайнов для CI и не надо дублировать код в devenv. Также меньше возможностей ошибиться при сборке - скрипты сами сделают всё, что нужно.ndebс этого момента стал deprecated, о чём пишется WARNING. -
Почему в Python-библиотеках не пишем Multi-Arch в пакетах?
Как минимум потому что это не делают даже в Debian.
Перед тем как открывать PR, убедитесь, что:
- Код проходит тесты (
pytest tests/); - Концы строк во всех файлах остаются
LF(это обеспечивает.gitattributes); - Пакет успешно собирается и на выходе получается deb-файл;
- Пакет проверен на реальном контроллере:
- Устанавливается;
- После установки импортируется namespace-пакет;
- Сервис запускается сам после установки;
- Сервис автоматически стартует после перезагрузки контроллера;
- Пакет удаляется.
Выполняется на самом Wiren Board (арх all, подойдёт любой).
Репозитории WB на контроллере должны быть настроены — из них тянется python3-wb-common.
# 1. Инструменты сборки (один раз на контроллер)
sudo apt update
sudo apt install -y build-essential devscripts equivs git
# 2. Копия из своей ветки
GIT_BRANCH_NAME="feature/branch-name"
git clone -b "${GIT_BRANCH_NAME}" --single-branch \
https://github.com/wirenboard/wb-python-service-template.git
cd wb-python-service-template
# 3. Build-зависимости из debian/control и сборка пакета
sudo mk-build-deps -ir debian/control
dpkg-buildpackage -us -uc -bДалее нужно проверить что пакета корректно собран и сервис поднимается сам
# 1. Установка собранного пакета
sudo apt install -y ../wb-python-service-template_*.deb
# 2. Проверка импорта namespace-пакета
python3 -c "import wb.python_service_template.main as m; print('import OK:', m.main)"
# 3. Проверка работы сервиса
systemctl is-enabled wb-python-service-template # ожидается: enabled
systemctl status wb-python-service-template # ожидается: active (running)
# 4. Проверка автозапуска после перезагрузки
sudo reboot
# после загрузки снова зайти по SSH и проверить, что сервис поднялся сам:
systemctl status wb-python-service-template # ожидается: active (running)
# 5. Удаление после проверки
sudo apt purge -y wb-python-service-templateПри успешной сборке pytest прогонит tests/ (шаг сборки dh_auto_test), а после установки
сервис включится автоматически благодаря секции [Install] в юните.