deploy examples
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
# systemd-службы сетевого моста
|
||||
|
||||
Автозапуск `tools/bridge.py` как служб: `cart-bridge-tx` (отправитель, рядом с
|
||||
пультом) и `cart-bridge-rx` (приёмник, рядом с тележкой). На каждой машине
|
||||
включается ровно одна роль.
|
||||
|
||||
## Установка
|
||||
|
||||
На машине-отправителе:
|
||||
|
||||
```sh
|
||||
sudo ./install-bridge.sh tx
|
||||
```
|
||||
|
||||
На машине-приёмнике:
|
||||
|
||||
```sh
|
||||
sudo ./install-bridge.sh rx
|
||||
```
|
||||
|
||||
Установщик подставляет в юнит реальные пути (python из `.venv` проекта, если
|
||||
есть, иначе системный `python3`; `bridge.py`; рабочий каталог) и пользователя
|
||||
(того, кто вызвал `sudo`). Юниты кладутся в `/etc/systemd/system/`, конфиги —
|
||||
в `/etc/cart-bridge/{tx,rx}.env` (создаются из примеров, существующие не
|
||||
перезаписываются). Без аргумента (`none`) — только установка, без включения.
|
||||
|
||||
Интерпретатор можно задать явно: `sudo PYTHON=/usr/bin/python3 ./install-bridge.sh rx`.
|
||||
В выбранном python должен быть `pyserial`.
|
||||
|
||||
## Настройка
|
||||
|
||||
Отредактировать конфиг под свою сеть и ключ:
|
||||
|
||||
```sh
|
||||
sudoedit /etc/cart-bridge/tx.env # peer = адрес приёмника, общий ключ
|
||||
sudoedit /etc/cart-bridge/rx.env # bind, тот же ключ
|
||||
sudo systemctl restart cart-bridge-tx # применить
|
||||
```
|
||||
|
||||
Ключ `CART_BRIDGE_KEY` на обеих сторонах должен совпадать (HMAC-аутентификация
|
||||
пакетов; обязателен для интернета).
|
||||
|
||||
## Эксплуатация
|
||||
|
||||
```sh
|
||||
systemctl status cart-bridge-tx
|
||||
journalctl -u cart-bridge-tx -f # логи; на отправителе видно «приёмник отвечает/НЕ отвечает»
|
||||
sudo systemctl restart cart-bridge-tx
|
||||
sudo systemctl disable --now cart-bridge-tx
|
||||
```
|
||||
|
||||
Служба перезапускается при падении (`Restart=always`). Доступ к USB-порту STM
|
||||
даётся группами `dialout`/`plugdev` (прописаны в юните).
|
||||
@@ -0,0 +1,19 @@
|
||||
# Конфигурация службы приёмника (cart-bridge-rx). Копируется в
|
||||
# /etc/cart-bridge/rx.env установщиком. Переменные читает tools/bridge.py.
|
||||
|
||||
# Локальный UDP-адрес для приёма HOST:PORT.
|
||||
CART_BRIDGE_BIND=0.0.0.0:5005
|
||||
|
||||
# Общий ключ HMAC (ОБЯЗАТЕЛЕН для интернета). Должен совпадать с отправителем.
|
||||
CART_BRIDGE_KEY=change-me-shared-secret
|
||||
|
||||
# Необязательно: принимать пакеты только с этого адреса отправителя (фильтр по
|
||||
# хосту). Для интернета за NAT обычно оставляют пустым и полагаются на HMAC.
|
||||
#CART_BRIDGE_PEER=10.0.0.1
|
||||
|
||||
# Необязательно: путь к порту или подстрока product/serial. По умолчанию порт
|
||||
# ищется по USB product string CART-RX.
|
||||
#CART_BRIDGE_DEVICE=CART-RX
|
||||
|
||||
# Необязательно: уровень логов (DEBUG/INFO/WARNING).
|
||||
#CART_BRIDGE_LOG_LEVEL=INFO
|
||||
@@ -0,0 +1,18 @@
|
||||
[Unit]
|
||||
Description=Cart bridge receiver (role rx): сеть -> USB тележки
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=@USER@
|
||||
SupplementaryGroups=dialout plugdev
|
||||
EnvironmentFile=/etc/cart-bridge/rx.env
|
||||
WorkingDirectory=@WORKDIR@
|
||||
ExecStart=@PYTHON@ @BRIDGE@ --role rx
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,15 @@
|
||||
# Конфигурация службы отправителя (cart-bridge-tx). Копируется в
|
||||
# /etc/cart-bridge/tx.env установщиком. Переменные читает tools/bridge.py.
|
||||
|
||||
# Адрес приёмника HOST:PORT — куда слать управление.
|
||||
CART_BRIDGE_PEER=10.0.0.2:5005
|
||||
|
||||
# Общий ключ HMAC (ОБЯЗАТЕЛЕН для интернета). Должен совпадать с приёмником.
|
||||
CART_BRIDGE_KEY=change-me-shared-secret
|
||||
|
||||
# Необязательно: путь к порту или подстрока product/serial. По умолчанию порт
|
||||
# ищется по USB product string CART-TX.
|
||||
#CART_BRIDGE_DEVICE=CART-TX
|
||||
|
||||
# Необязательно: уровень логов (DEBUG/INFO/WARNING).
|
||||
#CART_BRIDGE_LOG_LEVEL=INFO
|
||||
@@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Description=Cart bridge sender (role tx): пульт USB -> сеть
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# не упираться в лимит перезапусков при флапе сети/USB
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=@USER@
|
||||
# доступ к последовательному порту STM (dialout) и к USB-дескрипторам (plugdev)
|
||||
SupplementaryGroups=dialout plugdev
|
||||
EnvironmentFile=/etc/cart-bridge/tx.env
|
||||
WorkingDirectory=@WORKDIR@
|
||||
ExecStart=@PYTHON@ @BRIDGE@ --role tx
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
# Установка systemd-служб сетевого моста тележки.
|
||||
#
|
||||
# sudo ./install-bridge.sh [tx|rx|both|none]
|
||||
#
|
||||
# Аргумент выбирает, какую службу включить и запустить на ЭТОЙ машине
|
||||
# (tx — рядом с пультом, rx — рядом с тележкой). Без аргумента юниты только
|
||||
# ставятся, но не включаются. Файлы юнитов и шаблоны конфигов берутся из этого
|
||||
# каталога; пути к python и bridge.py подставляются автоматически.
|
||||
set -euo pipefail
|
||||
|
||||
SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TOOLS="$(cd "$SELF/../tools" && pwd)"
|
||||
REPO="$(cd "$SELF/../../.." && pwd)"
|
||||
BRIDGE="$TOOLS/bridge.py"
|
||||
WORKDIR="$TOOLS"
|
||||
ENABLE="${1:-none}"
|
||||
|
||||
case "$ENABLE" in tx|rx|both|none) ;; *) echo "аргумент: tx|rx|both|none" >&2; exit 2;; esac
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "нужны права root — перезапускаюсь через sudo"
|
||||
exec sudo -E PYTHON="${PYTHON:-}" bash "$0" "$ENABLE"
|
||||
fi
|
||||
|
||||
TARGET_USER="${SUDO_USER:-root}"
|
||||
|
||||
# интерпретатор: venv проекта, если есть, иначе системный python3
|
||||
PYTHON="${PYTHON:-}"
|
||||
if [ -z "$PYTHON" ]; then
|
||||
if [ -x "$REPO/.venv/bin/python" ]; then
|
||||
PYTHON="$REPO/.venv/bin/python"
|
||||
else
|
||||
PYTHON="$(command -v python3)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "python : $PYTHON"
|
||||
echo "bridge : $BRIDGE"
|
||||
echo "user : $TARGET_USER"
|
||||
|
||||
if ! "$PYTHON" -c 'import serial' 2>/dev/null; then
|
||||
echo "ВНИМАНИЕ: в $PYTHON нет pyserial — поставь: $PYTHON -m pip install pyserial" >&2
|
||||
fi
|
||||
|
||||
gen_unit() { # <role>
|
||||
local role="$1"
|
||||
sed -e "s|@PYTHON@|$PYTHON|g" -e "s|@BRIDGE@|$BRIDGE|g" \
|
||||
-e "s|@WORKDIR@|$WORKDIR|g" -e "s|@USER@|$TARGET_USER|g" \
|
||||
"$SELF/cart-bridge-$role.service" > "/etc/systemd/system/cart-bridge-$role.service"
|
||||
echo "установлен юнит /etc/systemd/system/cart-bridge-$role.service"
|
||||
}
|
||||
|
||||
install -d -m 755 /etc/cart-bridge
|
||||
for role in tx rx; do
|
||||
gen_unit "$role"
|
||||
conf="/etc/cart-bridge/$role.env"
|
||||
if [ ! -e "$conf" ]; then
|
||||
install -m 600 "$SELF/cart-bridge-$role.env.example" "$conf"
|
||||
echo "создан конфиг $conf (ОТРЕДАКТИРУЙ: peer/bind и ключ)"
|
||||
else
|
||||
echo "конфиг $conf уже есть — не трогаю"
|
||||
fi
|
||||
done
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
enable_one() { # <role>
|
||||
systemctl enable --now "cart-bridge-$1.service"
|
||||
echo "включена и запущена cart-bridge-$1.service"
|
||||
}
|
||||
case "$ENABLE" in
|
||||
tx) enable_one tx ;;
|
||||
rx) enable_one rx ;;
|
||||
both) enable_one tx; enable_one rx ;;
|
||||
none) echo "юниты установлены, не включены. Включить: systemctl enable --now cart-bridge-tx (или -rx)";;
|
||||
esac
|
||||
|
||||
echo "готово. Логи: journalctl -u cart-bridge-tx -f (или -rx)"
|
||||
Reference in New Issue
Block a user