mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-08-12 03:43:04 +02:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6de2b23266 | |||
| 864030283c | |||
| 751c9e3807 | |||
| fbbc7e6844 | |||
| 4d095dad42 | |||
| fcaad1dacf | |||
| e2ae7e18a6 | |||
| 11f8ea2f43 | |||
| d24a346cf7 | |||
| af6bea5bbe | |||
| 9846666076 | |||
| 42340f683f | |||
| 27e68167d5 | |||
| f0408d263d | |||
| 135d6b1d8d | |||
| 9748058010 | |||
| cc0dc2ffd6 |
+4
-4
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# Published image to run. Use a different repository or tag if you are testing
|
# Published image to run. Use a different repository or tag if you are testing
|
||||||
# a fork or a specific release.
|
# a fork or a specific release.
|
||||||
PYMC_REPEATER_IMAGE=pymcdev/openhop-repeater:main
|
OPENHOP_REPEATER_IMAGE=openhop/openhop-repeater:main
|
||||||
|
|
||||||
# Storage defaults to Docker named volumes. This is the safest option for
|
# Storage defaults to Docker named volumes. This is the safest option for
|
||||||
# Portainer and fresh installs because Docker preserves the image ownership.
|
# Portainer and fresh installs because Docker preserves the image ownership.
|
||||||
@@ -12,8 +12,8 @@ PYMC_REPEATER_IMAGE=pymcdev/openhop-repeater:main
|
|||||||
# sudo mkdir -p /opt/openhop-repeater/config /opt/openhop-repeater/data
|
# sudo mkdir -p /opt/openhop-repeater/config /opt/openhop-repeater/data
|
||||||
# sudo chown -R 15888:15888 /opt/openhop-repeater/config /opt/openhop-repeater/data
|
# sudo chown -R 15888:15888 /opt/openhop-repeater/config /opt/openhop-repeater/data
|
||||||
# Then uncomment and adjust these paths:
|
# Then uncomment and adjust these paths:
|
||||||
# PYMC_CONFIG_VOLUME=/opt/openhop-repeater/config
|
# OPENHOP_CONFIG_VOLUME=/opt/openhop-repeater/config
|
||||||
# PYMC_DATA_VOLUME=/opt/openhop-repeater/data
|
# OPENHOP_DATA_VOLUME=/opt/openhop-repeater/data
|
||||||
|
|
||||||
# Serial/SPI/GPIO access uses the host's numeric group IDs. Check your host with:
|
# Serial/SPI/GPIO access uses the host's numeric group IDs. Check your host with:
|
||||||
# getent group dialout
|
# getent group dialout
|
||||||
@@ -29,6 +29,6 @@ GPIO_GID=986
|
|||||||
SPI_GID=989
|
SPI_GID=989
|
||||||
|
|
||||||
# Local build only. These are used by docker-compose.build.yml if you build the
|
# Local build only. These are used by docker-compose.build.yml if you build the
|
||||||
# image yourself instead of pulling PYMC_REPEATER_IMAGE.
|
# image yourself instead of pulling OPENHOP_REPEATER_IMAGE.
|
||||||
PUID=15888
|
PUID=15888
|
||||||
PGID=15888
|
PGID=15888
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ on:
|
|||||||
image_repository:
|
image_repository:
|
||||||
description: "Docker image repository to publish to"
|
description: "Docker image repository to publish to"
|
||||||
required: false
|
required: false
|
||||||
default: "pymcdev/openhop-repeater"
|
default: "openhop/openhop-repeater"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
elif [ "${{ github.repository }}" = "yellowcooln/openhop_repeater" ]; then
|
elif [ "${{ github.repository }}" = "yellowcooln/openhop_repeater" ]; then
|
||||||
image_repository="yellowcooln/openhop-repeater"
|
image_repository="yellowcooln/openhop-repeater"
|
||||||
else
|
else
|
||||||
image_repository="pymcdev/openhop-repeater"
|
image_repository="openhop/openhop-repeater"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Using image repository: ${image_repository}"
|
echo "Using image repository: ${image_repository}"
|
||||||
@@ -107,5 +107,5 @@ jobs:
|
|||||||
-X POST \
|
-X POST \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
-H "Authorization: Bearer ${DISPATCH_TOKEN}" \
|
-H "Authorization: Bearer ${DISPATCH_TOKEN}" \
|
||||||
https://api.github.com/repos/pyMC-dev/pyMC-HA-Add-on/dispatches \
|
https://api.github.com/repos/openhop-dev/openHop-HA-Add-on/dispatches \
|
||||||
-d "{\"event_type\":\"sync-upstream-channel\",\"client_payload\":{\"channel\":\"${CHANNEL}\",\"revision\":\"${REVISION}\"}}"
|
-d "{\"event_type\":\"sync-upstream-channel\",\"client_payload\":{\"channel\":\"${CHANNEL}\",\"revision\":\"${REVISION}\"}}"
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Lightweight Python MeshCore repeater daemon built on `openhop_core`.
|
Lightweight Python MeshCore repeater daemon built on `openhop_core`.
|
||||||
|
|
||||||
|
Formerly `pyMC_Repeater` built on `pyMC_core`.
|
||||||
|
|
||||||
openHop Repeater is designed to run continuously on low-power Linux hardware such
|
openHop Repeater is designed to run continuously on low-power Linux hardware such
|
||||||
as Raspberry Pi-class devices, Proxmox LXC containers, and network-attached
|
as Raspberry Pi-class devices, Proxmox LXC containers, and network-attached
|
||||||
radio modems. It forwards LoRa packets, exposes a web dashboard, and provides
|
radio modems. It forwards LoRa packets, exposes a web dashboard, and provides
|
||||||
@@ -111,8 +113,8 @@ sudo apt install git -y
|
|||||||
### Clone The Repository
|
### Clone The Repository
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/openhop-dev/openhop-repeater.git
|
git clone https://github.com/openhop-dev/openhop_repeater.git
|
||||||
cd openhop-repeater
|
cd openhop_repeater
|
||||||
```
|
```
|
||||||
|
|
||||||
### Quick Install
|
### Quick Install
|
||||||
@@ -258,7 +260,7 @@ The web interface can upgrade an installation or switch branches.
|
|||||||
### CLI
|
### CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd openhop-repeater
|
cd openhop_repeater
|
||||||
sudo bash ./manage.sh upgrade
|
sudo bash ./manage.sh upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -295,7 +297,7 @@ Hardware, choose one:
|
|||||||
Run this command on the Proxmox host, not inside a container:
|
Run this command on the Proxmox host, not inside a container:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/pyMC-dev/openhop-repeater/main/scripts/proxmox-install.sh)"
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/openhop-dev/openhop_repeater/main/scripts/proxmox-install.sh)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `main` in the URL with another branch name if needed.
|
Replace `main` in the URL with another branch name if needed.
|
||||||
@@ -416,7 +418,7 @@ that source as a directory, which breaks startup.
|
|||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
1. Copy `.env.example` to `.env`.
|
1. Copy `.env.example` to `.env`.
|
||||||
2. Review `.env` and update `PYMC_REPEATER_IMAGE`, `DIALOUT_GID`,
|
2. Review `.env` and update `OPENHOP_REPEATER_IMAGE`, `DIALOUT_GID`,
|
||||||
`GPIO_GID`, or `SPI_GID` if needed.
|
`GPIO_GID`, or `SPI_GID` if needed.
|
||||||
3. Configure `docker-compose.yml` for your hardware and device paths.
|
3. Configure `docker-compose.yml` for your hardware and device paths.
|
||||||
4. Uncomment the USB device mapping only if your host has that device path.
|
4. Uncomment the USB device mapping only if your host has that device path.
|
||||||
@@ -431,7 +433,7 @@ docker compose up -d
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
openhop-repeater:
|
openhop-repeater:
|
||||||
image: ${PYMC_REPEATER_IMAGE:-pymcdev/openhop-repeater:main}
|
image: ${OPENHOP_REPEATER_IMAGE:-${PYMC_REPEATER_IMAGE:-openhop/openhop-repeater:main}}
|
||||||
container_name: openhop-repeater
|
container_name: openhop-repeater
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
@@ -455,8 +457,8 @@ services:
|
|||||||
- plugdev
|
- plugdev
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- ${PYMC_CONFIG_VOLUME:-openhop-repeater-config}:/etc/openhop_repeater
|
- ${OPENHOP_CONFIG_VOLUME:-${PYMC_CONFIG_VOLUME:-openhop-repeater-config}}:/etc/openhop_repeater
|
||||||
- ${PYMC_DATA_VOLUME:-openhop-repeater-data}:/var/lib/openhop_repeater
|
- ${OPENHOP_DATA_VOLUME:-${PYMC_DATA_VOLUME:-openhop-repeater-data}}:/var/lib/openhop_repeater
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
openhop-repeater-config:
|
openhop-repeater-config:
|
||||||
@@ -518,7 +520,7 @@ Pre-commit hooks will automatically:
|
|||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
- [pyMC Core](https://github.com/openhop-dev/openhop-core)
|
- [pyMC Core](https://github.com/openhop-dev/openhop_core)
|
||||||
- [MeshCore Discord](https://meshcore.gg)
|
- [MeshCore Discord](https://meshcore.gg)
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ R2_BASE_URL="https://wheel.pymc.dev/pymc_build_deps"
|
|||||||
PIWHEELS_INDEX_URL="https://www.piwheels.org/simple"
|
PIWHEELS_INDEX_URL="https://www.piwheels.org/simple"
|
||||||
R2_ENABLED=1
|
R2_ENABLED=1
|
||||||
YQ_VERSION="${YQ_VERSION:-v4.44.3}"
|
YQ_VERSION="${YQ_VERSION:-v4.44.3}"
|
||||||
PYMC_CORE_REPO="${PYMC_CORE_REPO:-https://github.com/rightup/openhop-core.git}"
|
PYMC_CORE_REPO="${PYMC_CORE_REPO:-https://github.com/openhop-dev/openhop_core.git}"
|
||||||
PYMC_CORE_REF="${PYMC_CORE_REF:-}"
|
PYMC_CORE_REF="${PYMC_CORE_REF:-}"
|
||||||
PYMC_CORE_LOCAL_DIR="${PYMC_CORE_LOCAL_DIR:-}"
|
PYMC_CORE_LOCAL_DIR="${PYMC_CORE_LOCAL_DIR:-}"
|
||||||
PYMC_SKIP_BUILDROOT_DEP_INSTALL="${PYMC_SKIP_BUILDROOT_DEP_INSTALL:-0}"
|
PYMC_SKIP_BUILDROOT_DEP_INSTALL="${PYMC_SKIP_BUILDROOT_DEP_INSTALL:-0}"
|
||||||
@@ -1247,12 +1247,12 @@ prepare_git_version() {
|
|||||||
git -C "$SCRIPT_DIR" fetch --tags 2>/dev/null || true
|
git -C "$SCRIPT_DIR" fetch --tags 2>/dev/null || true
|
||||||
git_version=$(python3 -m setuptools_scm 2>/dev/null || echo "1.0.5")
|
git_version=$(python3 -m setuptools_scm 2>/dev/null || echo "1.0.5")
|
||||||
export SETUPTOOLS_SCM_PRETEND_VERSION="$git_version"
|
export SETUPTOOLS_SCM_PRETEND_VERSION="$git_version"
|
||||||
export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYMC_REPEATER="$git_version"
|
export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OPENHOP_REPEATER="$git_version"
|
||||||
info "Using version: $git_version"
|
info "Using version: $git_version"
|
||||||
else
|
else
|
||||||
git_version="1.0.5"
|
git_version="1.0.5"
|
||||||
export SETUPTOOLS_SCM_PRETEND_VERSION="$git_version"
|
export SETUPTOOLS_SCM_PRETEND_VERSION="$git_version"
|
||||||
export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYMC_REPEATER="$git_version"
|
export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OPENHOP_REPEATER="$git_version"
|
||||||
info "Using fallback version: $git_version"
|
info "Using fallback version: $git_version"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -15,7 +15,7 @@ Build-Depends: debhelper-compat (= 13),
|
|||||||
python3-psutil,
|
python3-psutil,
|
||||||
git
|
git
|
||||||
Standards-Version: 4.6.2
|
Standards-Version: 4.6.2
|
||||||
Homepage: https://github.com/rightup/openhop-repeater
|
Homepage: https://github.com/openhop-dev/openhop_repeater
|
||||||
X-Python3-Version: >= 3.9
|
X-Python3-Version: >= 3.9
|
||||||
|
|
||||||
Package: openhop-repeater
|
Package: openhop-repeater
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
openhop-repeater:
|
openhop-repeater:
|
||||||
image: ${PYMC_REPEATER_IMAGE:-pymcdev/openhop-repeater:main}
|
image: ${OPENHOP_REPEATER_IMAGE:-${PYMC_REPEATER_IMAGE:-openhop/openhop-repeater:main}}
|
||||||
container_name: openhop-repeater
|
container_name: openhop-repeater
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
@@ -21,8 +21,8 @@ services:
|
|||||||
- "${SPI_GID:-989}"
|
- "${SPI_GID:-989}"
|
||||||
- plugdev
|
- plugdev
|
||||||
volumes:
|
volumes:
|
||||||
- ${PYMC_CONFIG_VOLUME:-openhop-repeater-config}:/etc/openhop_repeater
|
- ${OPENHOP_CONFIG_VOLUME:-${PYMC_CONFIG_VOLUME:-openhop-repeater-config}}:/etc/openhop_repeater
|
||||||
- ${PYMC_DATA_VOLUME:-openhop-repeater-data}:/var/lib/openhop_repeater
|
- ${OPENHOP_DATA_VOLUME:-${PYMC_DATA_VOLUME:-openhop-repeater-data}}:/var/lib/openhop_repeater
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
openhop-repeater-config:
|
openhop-repeater-config:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set -eu
|
|||||||
|
|
||||||
INSTALL_DIR="${INSTALL_DIR:-/opt/openhop_repeater}"
|
INSTALL_DIR="${INSTALL_DIR:-/opt/openhop_repeater}"
|
||||||
CONFIG_DIR="${CONFIG_DIR:-/etc/openhop_repeater}"
|
CONFIG_DIR="${CONFIG_DIR:-/etc/openhop_repeater}"
|
||||||
CONFIG_PATH="${PYMC_REPEATER_CONFIG:-${CONFIG_DIR}/config.yaml}"
|
CONFIG_PATH="${OPENHOP_REPEATER_CONFIG:-${PYMC_REPEATER_CONFIG:-${CONFIG_DIR}/config.yaml}}"
|
||||||
EXAMPLE_PATH="${CONFIG_DIR}/config.yaml.example"
|
EXAMPLE_PATH="${CONFIG_DIR}/config.yaml.example"
|
||||||
BUNDLED_EXAMPLE_PATH="${INSTALL_DIR}/config.yaml.example"
|
BUNDLED_EXAMPLE_PATH="${INSTALL_DIR}/config.yaml.example"
|
||||||
RUNTIME_USER="${USER:-repeater}"
|
RUNTIME_USER="${USER:-repeater}"
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ ENV INSTALL_DIR=/opt/openhop_repeater \
|
|||||||
HOME_DIR=/home/${USER} \
|
HOME_DIR=/home/${USER} \
|
||||||
PATH=/home/${USER}/.local/bin:${PATH} \
|
PATH=/home/${USER}/.local/bin:${PATH} \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYMC_REPEATER=${PACKAGE_VERSION} \
|
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OPENHOP_REPEATER=${PACKAGE_VERSION} \
|
||||||
PUID=${PUID} \
|
PUID=${PUID} \
|
||||||
PGID=${PGID} \
|
PGID=${PGID} \
|
||||||
DIALOUT_GID=${DIALOUT_GID} \
|
DIALOUT_GID=${DIALOUT_GID} \
|
||||||
|
|||||||
+4
-4
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# Published image to run. Use a different repository or tag if you are testing
|
# Published image to run. Use a different repository or tag if you are testing
|
||||||
# a fork or a specific release.
|
# a fork or a specific release.
|
||||||
PYMC_REPEATER_IMAGE=pymcdev/openhop-repeater:main
|
OPENHOP_REPEATER_IMAGE=openhop/openhop-repeater:main
|
||||||
|
|
||||||
# Storage defaults to Docker named volumes. This is the safest option for
|
# Storage defaults to Docker named volumes. This is the safest option for
|
||||||
# Portainer and fresh installs because Docker preserves the image ownership.
|
# Portainer and fresh installs because Docker preserves the image ownership.
|
||||||
@@ -12,8 +12,8 @@ PYMC_REPEATER_IMAGE=pymcdev/openhop-repeater:main
|
|||||||
# sudo mkdir -p /opt/openhop-repeater/config /opt/openhop-repeater/data
|
# sudo mkdir -p /opt/openhop-repeater/config /opt/openhop-repeater/data
|
||||||
# sudo chown -R 15888:15888 /opt/openhop-repeater/config /opt/openhop-repeater/data
|
# sudo chown -R 15888:15888 /opt/openhop-repeater/config /opt/openhop-repeater/data
|
||||||
# Then uncomment and adjust these paths:
|
# Then uncomment and adjust these paths:
|
||||||
# PYMC_CONFIG_VOLUME=/opt/openhop-repeater/config
|
# OPENHOP_CONFIG_VOLUME=/opt/openhop-repeater/config
|
||||||
# PYMC_DATA_VOLUME=/opt/openhop-repeater/data
|
# OPENHOP_DATA_VOLUME=/opt/openhop-repeater/data
|
||||||
|
|
||||||
# SPI/GPIO access uses the host's numeric group IDs. Check your host with:
|
# SPI/GPIO access uses the host's numeric group IDs. Check your host with:
|
||||||
# getent group gpio
|
# getent group gpio
|
||||||
@@ -26,6 +26,6 @@ GPIO_GID=986
|
|||||||
SPI_GID=989
|
SPI_GID=989
|
||||||
|
|
||||||
# Local build only. These are used by docker-compose.build.yml if you build the
|
# Local build only. These are used by docker-compose.build.yml if you build the
|
||||||
# image yourself instead of pulling PYMC_REPEATER_IMAGE.
|
# image yourself instead of pulling OPENHOP_REPEATER_IMAGE.
|
||||||
PUID=15888
|
PUID=15888
|
||||||
PGID=15888
|
PGID=15888
|
||||||
|
|||||||
@@ -88,14 +88,51 @@ migrate_legacy_paths() {
|
|||||||
migrate_one_path "$LEGACY_PYMC_INSTALL_DIR" "$INSTALL_DIR" "install"
|
migrate_one_path "$LEGACY_PYMC_INSTALL_DIR" "$INSTALL_DIR" "install"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_service_user_home() {
|
||||||
|
local current_home
|
||||||
|
|
||||||
|
if ! id "$SERVICE_USER" &>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_home="$(getent passwd "$SERVICE_USER" | cut -d: -f6)"
|
||||||
|
if [ -z "$current_home" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$current_home" != "$DATA_DIR" ]; then
|
||||||
|
mkdir -p "$DATA_DIR" 2>/dev/null || true
|
||||||
|
usermod -d "$DATA_DIR" "$SERVICE_USER" 2>/dev/null || true
|
||||||
|
echo " ✓ Updated $SERVICE_USER home directory: $current_home -> $DATA_DIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Create (or re-create) the dedicated venv for openhop_repeater
|
# Create (or re-create) the dedicated venv for openhop_repeater
|
||||||
ensure_venv() {
|
ensure_venv() {
|
||||||
|
local recreate=0
|
||||||
|
|
||||||
if [ ! -x "$VENV_PYTHON" ]; then
|
if [ ! -x "$VENV_PYTHON" ]; then
|
||||||
echo ">>> Creating virtual environment at $VENV_DIR ..."
|
recreate=1
|
||||||
python3 -m venv --system-site-packages "$VENV_DIR"
|
elif ! "$VENV_PYTHON" -c 'import sys; print(sys.executable)' >/dev/null 2>&1; then
|
||||||
# Upgrade pip inside the venv
|
# Venv python exists but points to a missing interpreter (stale venv).
|
||||||
"$VENV_PIP" install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
recreate=1
|
||||||
|
elif ! "$VENV_PYTHON" -m pip --version >/dev/null 2>&1; then
|
||||||
|
# Pip script/shebang can break after Python upgrades; treat as stale.
|
||||||
|
recreate=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$recreate" -eq 1 ]; then
|
||||||
|
if [ -d "$VENV_DIR" ]; then
|
||||||
|
echo ">>> Rebuilding broken virtual environment at $VENV_DIR ..."
|
||||||
|
rm -rf "$VENV_DIR"
|
||||||
|
else
|
||||||
|
echo ">>> Creating virtual environment at $VENV_DIR ..."
|
||||||
|
fi
|
||||||
|
python3 -m venv --system-site-packages "$VENV_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always use python -m pip so we don't rely on a potentially stale pip wrapper.
|
||||||
|
"$VENV_PYTHON" -m pip install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Migrate an existing system-pip install into the venv.
|
# Migrate an existing system-pip install into the venv.
|
||||||
@@ -105,6 +142,7 @@ migrate_to_venv() {
|
|||||||
|
|
||||||
# 1. Ensure the venv exists
|
# 1. Ensure the venv exists
|
||||||
ensure_venv
|
ensure_venv
|
||||||
|
ensure_service_user_home
|
||||||
|
|
||||||
# 2. Remove legacy PYTHONPATH from the service unit
|
# 2. Remove legacy PYTHONPATH from the service unit
|
||||||
local svc_unit="/etc/systemd/system/openhop-repeater.service"
|
local svc_unit="/etc/systemd/system/openhop-repeater.service"
|
||||||
@@ -424,6 +462,7 @@ install_repeater() {
|
|||||||
if ! id "$SERVICE_USER" &>/dev/null; then
|
if ! id "$SERVICE_USER" &>/dev/null; then
|
||||||
useradd --system --home "$DATA_DIR" --shell /sbin/nologin "$SERVICE_USER"
|
useradd --system --home "$DATA_DIR" --shell /sbin/nologin "$SERVICE_USER"
|
||||||
fi
|
fi
|
||||||
|
ensure_service_user_home
|
||||||
|
|
||||||
disable_legacy_services
|
disable_legacy_services
|
||||||
|
|
||||||
@@ -567,7 +606,7 @@ fi
|
|||||||
if [ ! -x "$VENV_PYTHON" ]; then
|
if [ ! -x "$VENV_PYTHON" ]; then
|
||||||
echo "[pymc-do-upgrade] Creating venv at $VENV_DIR ..."
|
echo "[pymc-do-upgrade] Creating venv at $VENV_DIR ..."
|
||||||
python3 -m venv --system-site-packages "$VENV_DIR"
|
python3 -m venv --system-site-packages "$VENV_DIR"
|
||||||
"$VENV_PIP" install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
"$VENV_PYTHON" -m pip install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
# ---- Migration: clean up legacy service unit issues ----
|
# ---- Migration: clean up legacy service unit issues ----
|
||||||
SVC_UNIT=/etc/systemd/system/openhop-repeater.service
|
SVC_UNIT=/etc/systemd/system/openhop-repeater.service
|
||||||
@@ -615,15 +654,15 @@ if [ -n "$ARCH_TAG" ]; then
|
|||||||
PY_TAG=$("$VENV_PYTHON" -c 'import sys; v=f"cp{sys.version_info.major}{sys.version_info.minor}"; print(f"{v}-{v}")' 2>/dev/null || echo "cp311-cp311")
|
PY_TAG=$("$VENV_PYTHON" -c 'import sys; v=f"cp{sys.version_info.major}{sys.version_info.minor}"; print(f"{v}-{v}")' 2>/dev/null || echo "cp311-cp311")
|
||||||
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
||||||
echo "[pymc-do-upgrade] Trying dependencies from R2 wheels..."
|
echo "[pymc-do-upgrade] Trying dependencies from R2 wheels..."
|
||||||
"$VENV_PIP" install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null || true
|
"$VENV_PYTHON" -m pip install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
# ---- Install openhop_repeater from git ----
|
# ---- Install openhop_repeater from git ----
|
||||||
if "$VENV_PIP" install \
|
if "$VENV_PYTHON" -m pip install \
|
||||||
--upgrade \
|
--upgrade \
|
||||||
--no-cache-dir \
|
--no-cache-dir \
|
||||||
"openhop_repeater[hardware] @ git+https://github.com/rightup/openhop-repeater.git@${CHANNEL}"; then
|
"openhop_repeater[hardware] @ git+https://github.com/openhop-dev/openhop_repeater.git@${CHANNEL}"; then
|
||||||
# Keep web/OTA updates aligned with manage.sh install/upgrade defaults.
|
# Keep web/OTA updates aligned with manage.sh install/upgrade defaults.
|
||||||
RADIO_BASE_URL="https://raw.githubusercontent.com/rightup/openhop-repeater/${CHANNEL}"
|
RADIO_BASE_URL="https://raw.githubusercontent.com/openhop-dev/openhop_repeater/${CHANNEL}"
|
||||||
RADIO_STORAGE_DIR="/var/lib/openhop_repeater"
|
RADIO_STORAGE_DIR="/var/lib/openhop_repeater"
|
||||||
mkdir -p "$RADIO_STORAGE_DIR"
|
mkdir -p "$RADIO_STORAGE_DIR"
|
||||||
wget -qO "$RADIO_STORAGE_DIR/radio-settings.json" "${RADIO_BASE_URL}/radio-settings.json" 2>/dev/null || true
|
wget -qO "$RADIO_STORAGE_DIR/radio-settings.json" "${RADIO_BASE_URL}/radio-settings.json" 2>/dev/null || true
|
||||||
@@ -687,7 +726,7 @@ UPGRADEEOF
|
|||||||
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
||||||
echo " Checking for R2 wheels (${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG})..."
|
echo " Checking for R2 wheels (${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG})..."
|
||||||
echo " Trying install from R2 pre-built wheels..."
|
echo " Trying install from R2 pre-built wheels..."
|
||||||
"$VENV_PIP" install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null && R2_SUCCESS=1 || R2_SUCCESS=0
|
"$VENV_PYTHON" -m pip install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null && R2_SUCCESS=1 || R2_SUCCESS=0
|
||||||
if [ "$R2_SUCCESS" -eq 1 ]; then
|
if [ "$R2_SUCCESS" -eq 1 ]; then
|
||||||
echo " ✓ R2 wheels installed"
|
echo " ✓ R2 wheels installed"
|
||||||
else
|
else
|
||||||
@@ -696,7 +735,7 @@ UPGRADEEOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if "$VENV_PIP" install --upgrade --no-cache-dir .[hardware]; then
|
if "$VENV_PYTHON" -m pip install --upgrade --no-cache-dir .[hardware]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "✓ Python package installation completed successfully!"
|
echo "✓ Python package installation completed successfully!"
|
||||||
|
|
||||||
@@ -868,6 +907,7 @@ upgrade_repeater() {
|
|||||||
|
|
||||||
echo "[1.6/9] Ensuring required directories..."
|
echo "[1.6/9] Ensuring required directories..."
|
||||||
mkdir -p "$INSTALL_DIR" "$CONFIG_DIR" "$LOG_DIR" "$DATA_DIR"
|
mkdir -p "$INSTALL_DIR" "$CONFIG_DIR" "$LOG_DIR" "$DATA_DIR"
|
||||||
|
ensure_service_user_home
|
||||||
|
|
||||||
echo "[2/9] Backing up configuration..."
|
echo "[2/9] Backing up configuration..."
|
||||||
if [ -d "$CONFIG_DIR" ]; then
|
if [ -d "$CONFIG_DIR" ]; then
|
||||||
@@ -1002,7 +1042,7 @@ fi
|
|||||||
if [ ! -x "$VENV_PYTHON" ]; then
|
if [ ! -x "$VENV_PYTHON" ]; then
|
||||||
echo "[pymc-do-upgrade] Creating venv at $VENV_DIR ..."
|
echo "[pymc-do-upgrade] Creating venv at $VENV_DIR ..."
|
||||||
python3 -m venv --system-site-packages "$VENV_DIR"
|
python3 -m venv --system-site-packages "$VENV_DIR"
|
||||||
"$VENV_PIP" install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
"$VENV_PYTHON" -m pip install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
# ---- Migration: clean up legacy service unit issues ----
|
# ---- Migration: clean up legacy service unit issues ----
|
||||||
SVC_UNIT=/etc/systemd/system/openhop-repeater.service
|
SVC_UNIT=/etc/systemd/system/openhop-repeater.service
|
||||||
@@ -1050,15 +1090,15 @@ python3 -m pip uninstall -y pymc_core 2>/dev/null || true
|
|||||||
PY_TAG=$("$VENV_PYTHON" -c 'import sys; v=f"cp{sys.version_info.major}{sys.version_info.minor}"; print(f"{v}-{v}")' 2>/dev/null || echo "cp311-cp311")
|
PY_TAG=$("$VENV_PYTHON" -c 'import sys; v=f"cp{sys.version_info.major}{sys.version_info.minor}"; print(f"{v}-{v}")' 2>/dev/null || echo "cp311-cp311")
|
||||||
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
||||||
echo "[pymc-do-upgrade] Trying dependencies from R2 wheels..."
|
echo "[pymc-do-upgrade] Trying dependencies from R2 wheels..."
|
||||||
"$VENV_PIP" install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null || true
|
"$VENV_PYTHON" -m pip install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
# ---- Install openhop_repeater from git ----
|
# ---- Install openhop_repeater from git ----
|
||||||
if "$VENV_PIP" install \
|
if "$VENV_PYTHON" -m pip install \
|
||||||
--upgrade \
|
--upgrade \
|
||||||
--no-cache-dir \
|
--no-cache-dir \
|
||||||
"openhop_repeater[hardware] @ git+https://github.com/rightup/openhop-repeater.git@${CHANNEL}"; then
|
"openhop_repeater[hardware] @ git+https://github.com/openhop-dev/openhop_repeater.git@${CHANNEL}"; then
|
||||||
# Keep web/OTA updates aligned with manage.sh install/upgrade defaults.
|
# Keep web/OTA updates aligned with manage.sh install/upgrade defaults.
|
||||||
RADIO_BASE_URL="https://raw.githubusercontent.com/rightup/openhop-repeater/${CHANNEL}"
|
RADIO_BASE_URL="https://raw.githubusercontent.com/openhop-dev/openhop_repeater/${CHANNEL}"
|
||||||
RADIO_STORAGE_DIR="/var/lib/openhop_repeater"
|
RADIO_STORAGE_DIR="/var/lib/openhop_repeater"
|
||||||
mkdir -p "$RADIO_STORAGE_DIR"
|
mkdir -p "$RADIO_STORAGE_DIR"
|
||||||
wget -qO "$RADIO_STORAGE_DIR/radio-settings.json" "${RADIO_BASE_URL}/radio-settings.json" 2>/dev/null || true
|
wget -qO "$RADIO_STORAGE_DIR/radio-settings.json" "${RADIO_BASE_URL}/radio-settings.json" 2>/dev/null || true
|
||||||
@@ -1122,7 +1162,7 @@ UPGRADEEOF
|
|||||||
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
WHEEL_BASE="${R2_BASE_URL}/${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG}"
|
||||||
echo " Checking for R2 wheels (${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG})..."
|
echo " Checking for R2 wheels (${ARCH_TAG}/${PLATFORM_TAG}/${PY_TAG})..."
|
||||||
echo " Trying install from R2 pre-built wheels..."
|
echo " Trying install from R2 pre-built wheels..."
|
||||||
"$VENV_PIP" install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null && R2_SUCCESS=1 || R2_SUCCESS=0
|
"$VENV_PYTHON" -m pip install --find-links "${WHEEL_BASE}/index.html" --no-cache-dir "pycryptodome>=3.23.0" "PyNaCl>=1.5.0" cffi "pyyaml>=6.0.0" 2>/dev/null && R2_SUCCESS=1 || R2_SUCCESS=0
|
||||||
if [ "$R2_SUCCESS" -eq 1 ]; then
|
if [ "$R2_SUCCESS" -eq 1 ]; then
|
||||||
echo " ✓ R2 wheels installed"
|
echo " ✓ R2 wheels installed"
|
||||||
else
|
else
|
||||||
@@ -1131,7 +1171,7 @@ UPGRADEEOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if "$VENV_PIP" install --upgrade --no-cache-dir .[hardware]; then
|
if "$VENV_PYTHON" -m pip install --upgrade --no-cache-dir .[hardware]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "✓ Package and dependencies upgraded successfully!"
|
echo "✓ Package and dependencies upgraded successfully!"
|
||||||
else
|
else
|
||||||
|
|||||||
+13
-6
@@ -195,7 +195,10 @@ def get_node_info(config: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
|
|
||||||
def load_config(config_path: Optional[str] = None) -> Dict[str, Any]:
|
def load_config(config_path: Optional[str] = None) -> Dict[str, Any]:
|
||||||
if config_path is None:
|
if config_path is None:
|
||||||
config_path = os.getenv("PYMC_REPEATER_CONFIG", "/etc/openhop_repeater/config.yaml")
|
config_path = os.getenv(
|
||||||
|
"OPENHOP_REPEATER_CONFIG",
|
||||||
|
os.getenv("PYMC_REPEATER_CONFIG", "/etc/openhop_repeater/config.yaml"),
|
||||||
|
)
|
||||||
|
|
||||||
# Check if config file exists
|
# Check if config file exists
|
||||||
if not Path(config_path).exists():
|
if not Path(config_path).exists():
|
||||||
@@ -301,10 +304,11 @@ def load_config(config_path: Optional[str] = None) -> Dict[str, Any]:
|
|||||||
else:
|
else:
|
||||||
config["repeater"]["identity_key"] = _load_or_create_identity_key()
|
config["repeater"]["identity_key"] = _load_or_create_identity_key()
|
||||||
|
|
||||||
if os.getenv("PYMC_REPEATER_LOG_LEVEL"):
|
env_log_level = os.getenv("OPENHOP_REPEATER_LOG_LEVEL", os.getenv("PYMC_REPEATER_LOG_LEVEL"))
|
||||||
|
if env_log_level:
|
||||||
if "logging" not in config:
|
if "logging" not in config:
|
||||||
config["logging"] = {}
|
config["logging"] = {}
|
||||||
config["logging"]["level"] = os.getenv("PYMC_REPEATER_LOG_LEVEL")
|
config["logging"]["level"] = env_log_level
|
||||||
|
|
||||||
config = _load_policy_engine_config(config, config_path)
|
config = _load_policy_engine_config(config, config_path)
|
||||||
|
|
||||||
@@ -323,7 +327,10 @@ def save_config(config_data: Dict[str, Any], config_path: Optional[str] = None)
|
|||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if config_path is None:
|
if config_path is None:
|
||||||
config_path = os.getenv("PYMC_REPEATER_CONFIG", "/etc/openhop_repeater/config.yaml")
|
config_path = os.getenv(
|
||||||
|
"OPENHOP_REPEATER_CONFIG",
|
||||||
|
os.getenv("PYMC_REPEATER_CONFIG", "/etc/openhop_repeater/config.yaml"),
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create backup of existing config
|
# Create backup of existing config
|
||||||
@@ -617,7 +624,7 @@ def get_radio_for_board(board_config: dict):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"pymc_tcp radio requires openhop-core >= the release that includes "
|
"pymc_tcp radio requires openhop-core >= the release that includes "
|
||||||
"PR pyMC-dev/openhop-core#68 (merged 2026-05-13). "
|
"the openhop-core release with TCP modem support. "
|
||||||
"Reinstall the [hardware] extra to pick it up."
|
"Reinstall the [hardware] extra to pick it up."
|
||||||
) from None
|
) from None
|
||||||
|
|
||||||
@@ -661,7 +668,7 @@ def get_radio_for_board(board_config: dict):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"pymc_usb radio requires openhop-core >= the release that includes "
|
"pymc_usb radio requires openhop-core >= the release that includes "
|
||||||
"PR pyMC-dev/openhop-core#68 (merged 2026-05-13). "
|
"the openhop-core release with TCP modem support. "
|
||||||
"Reinstall the [hardware] extra to pick it up."
|
"Reinstall the [hardware] extra to pick it up."
|
||||||
) from None
|
) from None
|
||||||
|
|
||||||
|
|||||||
@@ -1580,6 +1580,7 @@ class APIEndpoints:
|
|||||||
if cherrypy.request.method == "OPTIONS":
|
if cherrypy.request.method == "OPTIONS":
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
future = None
|
||||||
try:
|
try:
|
||||||
self._require_post()
|
self._require_post()
|
||||||
if not self.send_advert_func:
|
if not self.send_advert_func:
|
||||||
@@ -1588,7 +1589,6 @@ class APIEndpoints:
|
|||||||
return self._error("Event loop not available")
|
return self._error("Event loop not available")
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
future = None
|
|
||||||
future = asyncio.run_coroutine_threadsafe(self.send_advert_func(), self.event_loop)
|
future = asyncio.run_coroutine_threadsafe(self.send_advert_func(), self.event_loop)
|
||||||
result = future.result(timeout=10)
|
result = future.result(timeout=10)
|
||||||
return (
|
return (
|
||||||
@@ -1601,11 +1601,8 @@ class APIEndpoints:
|
|||||||
"Error sending advert: timeout waiting for advert transmission to complete",
|
"Error sending advert: timeout waiting for advert transmission to complete",
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
try:
|
if future is not None:
|
||||||
if future is not None:
|
future.cancel()
|
||||||
future.cancel()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return self._error("Timed out waiting for advert transmission after 10 seconds")
|
return self._error("Timed out waiting for advert transmission after 10 seconds")
|
||||||
except cherrypy.HTTPError:
|
except cherrypy.HTTPError:
|
||||||
# Re-raise HTTP errors (like 405 Method Not Allowed) without logging
|
# Re-raise HTTP errors (like 405 Method Not Allowed) without logging
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ info:
|
|||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
contact:
|
contact:
|
||||||
name: openHop Repeater
|
name: openHop Repeater
|
||||||
url: https://github.com/rightup/openhop-repeater
|
url: https://github.com/openhop-dev/openhop_repeater
|
||||||
|
|
||||||
servers:
|
servers:
|
||||||
- url: /api
|
- url: /api
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
# Creates an LXC container with USB passthrough and installs openHop Repeater
|
# Creates an LXC container with USB passthrough and installs openHop Repeater
|
||||||
#
|
#
|
||||||
# Usage (run on the Proxmox host):
|
# Usage (run on the Proxmox host):
|
||||||
# bash -c "$(curl -fsSL https://raw.githubusercontent.com/pyMC-dev/openhop-repeater/main/scripts/proxmox-install.sh)"
|
# bash -c "$(curl -fsSL https://raw.githubusercontent.com/openhop-dev/openhop_repeater/main/scripts/proxmox-install.sh)"
|
||||||
#
|
#
|
||||||
# License: MIT
|
# License: MIT
|
||||||
# Source: https://github.com/openhop-dev/openhop-repeater
|
# Source: https://github.com/openhop-dev/openhop_repeater
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ── Defaults ───────────────────────────────────────────────────────────────
|
# ── Defaults ───────────────────────────────────────────────────────────────
|
||||||
REPO="https://github.com/openhop-dev/openhop-repeater.git"
|
REPO="https://github.com/openhop-dev/openhop_repeater.git"
|
||||||
BRANCH="dev"
|
BRANCH="dev"
|
||||||
CT_TEMPLATE="debian-12-standard"
|
CT_TEMPLATE="debian-12-standard"
|
||||||
CT_RAM=1024
|
CT_RAM=1024
|
||||||
@@ -210,7 +210,7 @@ OS=\$(. /etc/os-release && echo \"\$NAME\")
|
|||||||
VER=\$(. /etc/os-release && echo \"\$VERSION_ID\")
|
VER=\$(. /etc/os-release && echo \"\$VERSION_ID\")
|
||||||
echo \"\"
|
echo \"\"
|
||||||
echo \" openHop Repeater LXC Container\"
|
echo \" openHop Repeater LXC Container\"
|
||||||
echo \" 🌐 GitHub: https://github.com/openhop-dev/openhop-repeater\"
|
echo \" 🌐 GitHub: https://github.com/openhop-dev/openhop_repeater\"
|
||||||
echo \"\"
|
echo \"\"
|
||||||
echo \" 🖥️ OS: \$OS - Version: \$VER\"
|
echo \" 🖥️ OS: \$OS - Version: \$VER\"
|
||||||
echo \" 🏠 Hostname: \$HOSTNAME\"
|
echo \" 🏠 Hostname: \$HOSTNAME\"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from repeater.config import BaselineCrcCounterRadio
|
from repeater.config import BaselineCrcCounterRadio, load_config
|
||||||
|
|
||||||
|
|
||||||
def test_baseline_crc_counter_radio_reports_delta_from_initial_raw_count():
|
def test_baseline_crc_counter_radio_reports_delta_from_initial_raw_count():
|
||||||
@@ -26,3 +26,20 @@ def test_baseline_crc_counter_radio_handles_delayed_modem_counter():
|
|||||||
|
|
||||||
raw.crc_error_count = 148
|
raw.crc_error_count = 148
|
||||||
assert radio.crc_error_count == 3
|
assert radio.crc_error_count == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config_prefers_openhop_env_names(tmp_path, monkeypatch):
|
||||||
|
legacy_path = tmp_path / "legacy.yaml"
|
||||||
|
openhop_path = tmp_path / "openhop.yaml"
|
||||||
|
legacy_path.write_text("repeater:\n identity_key: legacy\n", encoding="utf-8")
|
||||||
|
openhop_path.write_text("repeater:\n identity_key: openhop\n", encoding="utf-8")
|
||||||
|
|
||||||
|
monkeypatch.setenv("PYMC_REPEATER_CONFIG", str(legacy_path))
|
||||||
|
monkeypatch.setenv("OPENHOP_REPEATER_CONFIG", str(openhop_path))
|
||||||
|
monkeypatch.setenv("PYMC_REPEATER_LOG_LEVEL", "WARNING")
|
||||||
|
monkeypatch.setenv("OPENHOP_REPEATER_LOG_LEVEL", "DEBUG")
|
||||||
|
|
||||||
|
config = load_config()
|
||||||
|
|
||||||
|
assert config["repeater"]["identity_key"] == "openhop"
|
||||||
|
assert config["logging"]["level"] == "DEBUG"
|
||||||
|
|||||||
Reference in New Issue
Block a user