feat: bootstrap zigbee2mqtt app and diagnostics

This commit is contained in:
CyberMind-FR 2025-12-29 15:51:07 +01:00
parent d566a84dda
commit ec81952db1
12 changed files with 704 additions and 4 deletions

110
DOCS/ARCHITECTURE_NOTES.md Normal file
View File

@ -0,0 +1,110 @@
# SecuBox Architecture Notes
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
These notes summarize the repository structure, conventions, and supporting tooling gathered from `README.md`, `DOCS/QUICK-START.md`, `DOCS/DEVELOPMENT-GUIDELINES.md`, `DOCS/CODEX.md`, `DOCS/DOCUMENTATION-INDEX.md`, the various module READMEs, and the `secubox-tools/` scripts. Use this as a rapid orientation before extending the platform.
---
## Repository Layout (high level)
- **LuCI modules (`luci-app-*`)** Each app bundles a LuCI frontend (JS under `htdocs/luci-static`), RPCD backend (shell scripts in `root/usr/libexec/rpcd/`), UCI defaults (`root/etc/config/...`), ACL/menu descriptors, and module-specific README (see e.g. `luci-app-netdata-dashboard/README.md`). Naming conventions follow the “menu path = view path” and “RPC object name = file name” rules emphasized in `DOCS/QUICK-START.md`.
- **Themes (`luci-theme-secubox`)** Provides the shared SecuBox design tokens (`sh-*`, `sb-*` classes, palette, typography). All new UI should import `secubox-theme/secubox-theme.css` and leverage the CSS variables described in `DOCS/DEVELOPMENT-GUIDELINES.md`.
- **Core orchestration apps**
- `luci-app-secubox`: global hub UI.
- `luci-app-system-hub`: system health/remote assistance.
- `luci-app-network-modes`: prebuilt router/sniffer modes (bridges, AP, relay, etc.).
- `luci-app-vhost-manager`: reverse-proxy/vhost configuration (existing baseline for future work).
- **Tooling (`secubox-tools/`)** Bash/POSIX scripts for validation, building, deployment, permission repair, etc. The README documents workflows such as `validate-modules.sh`, `local-build.sh`, `fix-permissions.sh`, and `deploy-*.sh`.
- **Automation & Docs**
- `DOCS/` + `docs/`: mirrored, versioned documentation tree (design system, prompts, module templates, validation, permissions, etc.).
- `EXAMPLES/` and `templates/`: snippets and scaffolding.
- CI workflows live in `.github/workflows/` (referenced from README badges).
---
## Coding & Packaging Standards
Summarized from `DOCS/QUICK-START.md`, `DOCS/DEVELOPMENT-GUIDELINES.md`, and `DOCS/CODEX.md`:
1. **RPCD/ubus**
- RPC script filename **must** equal the ubus object (e.g., `root/usr/libexec/rpcd/luci.netdata-dashboard``object: 'luci.netdata-dashboard'`).
- RPC scripts are executable (755) while JS/CSS assets are 644.
- ACL and menu JSON entries shipped under `root/usr/share/rpcd/acl.d/` and `root/usr/share/luci/menu.d/`.
2. **LuCI Views**
- Menu `path` mirrors `htdocs/luci-static/resources/view/...` location.
- Use the SecuBox design system (`sh-*`/`sb-*` classes, Inter + JetBrains Mono, gradients). Avoid inline styles; rely on variables defined in `system-hub/common.css` or `secubox-theme`.
3. **UCI-first configuration**
- Every feature stores runtime state in `/etc/config/<module>`.
- CLI/scripts mutate config via `uci set/commit` and services watch UCI for changes.
4. **Service supervision**
- Prefer `procd` init scripts (`/etc/init.d/<service>`) for daemons; ensure restart semantics and `ENABLE` flags.
5. **Validation workflow**
- Run `./secubox-tools/validate-modules.sh` before PRs/releases. It checks permissions, RPC naming, LuCI assets, etc.
- Use `./secubox-tools/local-build.sh build <module>` for SDK builds; `fix-permissions.sh` to normalize deployments.
---
## Networking & Firewall Conventions
Derived from `luci-app-network-modes`, `luci-app-client-guardian`, and docs:
- Network modes (router/sniffer/AP) are implemented via UCI (`/etc/config/network`, `/etc/config/wireless`) with helper scripts ensuring safe defaults and backups before applying.
- Firewall zones follow OpenWrt defaults (lan/wan) with additional zones per feature (IoT, Guest, Quarantine). Changes should add backup/rollback paths and never remove LAN management access.
- Reverse proxy/vhost management currently relies on `luci-app-vhost-manager`; new work should extend its UCI schema rather than inventing a parallel config.
---
## Storage & Runtime Expectations
- Target platform: OpenWrt 24.10.x (and preview 25.12 RC) on ARM64 per `README.md`. Flash is limited; prefer `/srv` or external storage for large artifacts (Docker/LXC images).
- Overlay space must be <90% before deploying; quick-start docs include SSH check commands.
- `/tmp` is tmpfs; dont store persistent state there. Use `/srv/<app>` (Zigbee2MQTT), `/var/lib/<app>`, or configurable data roots.
---
## secubox-tools Highlights
- `validate-modules.sh` structural lint, permissions, ubus paths.
- `local-build.sh` OpenWrt SDK automation for building/testing packages (supports multiple arches).
- `fix-permissions.sh`, `deploy-*.sh` remote deployment helpers with backup/restore.
- These scripts are POSIX shell friendly and should be leveraged (or extended) for new installers/diagnostics.
---
## Existing Modules & Patterns
- **Monitoring dashboards** (Netdata, Netifyd, CrowdSec, WireGuard, Traffic Shaper, Bandwidth Manager) provide consistent patterns for:
- RPC APIs returning JSON for LuCI views.
- JS views using `view.extend`, `poll` auto-refresh, and stat cards built with design system classes.
- **Security & NAC modules** (Client Guardian, Auth Guardian) showcase how to integrate with firewall/zones, handle ACL, and present complex forms in LuCI.
- **Network orchestration** (Network Modes, System Hub) demonstrates multi-step wizards, health checks, and service controls.
- **Theme & Navigation** (luci-theme-secubox, luci-app-secubox) define tab components, cascade helpers, and global CSS/JS assets.
Use these modules as references when building new “apps” to ensure consistent UX, RPC layout, and packaging.
---
## Documentation Requirements
- Every new or edited `.md` must follow the metadata header and versioning rules defined in `DOCS/DOCUMENTATION-INDEX.md`.
- Cross-link relevant guides (Quick Start, Dev Guidelines, Codex) when introducing new features.
- For platform-level additions (App Store, Vhost manager, DMZ mode, etc.), update both `DOCS/` and `docs/` to keep mkdocs + markdown parity.
---
## Future Work Context
`TODO-ANALYSE.md` highlights ongoing documentation and automation initiatives:
- Standardize version headers across documentation.
- Add “See Also” cross-links.
- Maintain an archive folder for legacy docs.
- Build new testing/performance/security guides.
Keep these in mind when touching docs or adding new features so we converge toward the roadmap.
---
This document will evolve alongside the App Store, Docker/LXC frameworks, and new wizard/profile systems. Update it whenever repository architecture or workflows change significantly.

View File

@ -206,7 +206,16 @@ Follow this template when creating or revising documentation:
---
### 4. Tools & Scripts Documentation
### 4. Embedded Deployment Guides
#### **embedded/docker-zigbee2mqtt.md** 🔌
*Deploy Zigbee2MQTT via Docker on SecuBox (ARM64).*
Pointer: see `docs/embedded/docker-zigbee2mqtt.md` for the canonical version.
---
### 5. Tools & Scripts Documentation
#### **secubox-tools/README.md** 🔧
*Documentation for validation and build tools*
@ -225,7 +234,7 @@ Follow this template when creating or revising documentation:
---
### 5. Live Demo & Examples
### 6. Live Demo & Examples
#### **Live Demo Website** 🌐
*Production demo of all modules*

View File

@ -0,0 +1,7 @@
# Docker Zigbee2MQTT on OpenWrt ARM64
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
See `docs/embedded/docker-zigbee2mqtt.md` for the full guide. This mirrored copy is maintained for MkDocs builds. Keep both files in sync when editing.

View File

@ -0,0 +1,7 @@
# SecuBox Architecture Notes
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
This file mirrors the architecture summary maintained in `DOCS/ARCHITECTURE_NOTES.md`. See that copy for the canonical version.

View File

@ -206,7 +206,24 @@ Follow this template when creating or revising documentation:
---
### 4. Tools & Scripts Documentation
### 4. Embedded Deployment Guides
#### **embedded/docker-zigbee2mqtt.md** 🔌
*Deploy Zigbee2MQTT via Docker on SecuBox (ARM64).*
**Contents:**
- Prerequisite checklist (storage, cgroups, USB coordinator, Docker packages)
- Usage of `zigbee2mqttctl` (install/check/update/status/logs)
- UCI configuration reference (`/etc/config/zigbee2mqtt`)
- Troubleshooting + rollback/uninstall steps
**When to use:** Setting up Zigbee2MQTT before the LuCI UI is available.
**Size:** Short (~100 lines)
---
### 5. Tools & Scripts Documentation
#### **secubox-tools/README.md** 🔧
*Documentation for validation and build tools*
@ -225,7 +242,7 @@ Follow this template when creating or revising documentation:
---
### 5. Live Demo & Examples
### 6. Live Demo & Examples
#### **Live Demo Website** 🌐
*Production demo of all modules*

View File

@ -0,0 +1,115 @@
# Docker Zigbee2MQTT on OpenWrt ARM64
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
This guide explains how to deploy Zigbee2MQTT on SecuBox (OpenWrt ARM64) using the new `secubox-app-zigbee2mqtt` package. The workflow follows upstream guidance from zigbee2mqtt.io while respecting OpenWrt storage constraints, UCI configuration, and procd supervision.
---
## Prerequisites
- OpenWrt 24.10.x (or newer) ARM64 build with SecuBox feeds.
- Internet connectivity to fetch Docker images.
- USB coordinator exposed as `/dev/ttyACM0` (e.g., Sonoff Zigbee 3.0 dongle). Load `kmod-usb-acm`.
- At least 200MB free on overlay or external storage mounted at `/srv`.
- Cgroups v1/v2 enabled (verify `/sys/fs/cgroup` exists). Run `scripts/diagnose.sh` for sanity checks.
---
## Installation Steps
1. **Install the package:**
```sh
opkg update
opkg install secubox-app-zigbee2mqtt
```
2. **Bootstrap prerequisites (Docker, storage, config):**
```sh
zigbee2mqttctl install
```
This command will:
- verify kernel modules, cgroups, USB device, and storage
- install `dockerd`, `docker`, `containerd`, and `kmod-usb-acm`
- create `/srv/zigbee2mqtt/data` with `configuration.yaml`
- pull `ghcr.io/koenkk/zigbee2mqtt:latest`
- enable `/etc/init.d/zigbee2mqtt`
3. **Configure UCI (optional adjustments):**
```sh
uci set zigbee2mqtt.main.serial_port='/dev/ttyACM0'
uci set zigbee2mqtt.main.mqtt_host='mqtt://192.168.8.10:1883'
uci set zigbee2mqtt.main.mqtt_username='secubox'
uci set zigbee2mqtt.main.mqtt_password='secret'
uci commit zigbee2mqtt
```
4. **Start the service:**
```sh
/etc/init.d/zigbee2mqtt start
```
The procd service executes `docker run` in foreground mode and respawns automatically.
5. **Check logs and status:**
```sh
zigbee2mqttctl status
zigbee2mqttctl logs -f
```
6. **Upgrade to the latest image:**
```sh
zigbee2mqttctl update
```
This pulls the latest container and restarts the service if enabled.
---
## Files & Services
| Path | Purpose |
|------|---------|
| `/etc/config/zigbee2mqtt` | UCI configuration (serial port, MQTT, base topic, frontend port, data path). |
| `/etc/init.d/zigbee2mqtt` | procd wrapper that invokes `zigbee2mqttctl service-run`. |
| `/usr/sbin/zigbee2mqttctl` | Management CLI for install/check/update/status/logs. |
| `/srv/zigbee2mqtt/data` | Persistent Zigbee2MQTT state (configuration.yaml, database). |
---
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| `zigbee2mqttctl install` reports missing cgroups | Ensure `/sys/fs/cgroup` exists and cgroups are enabled in kernel config. |
| `/dev/ttyACM0` not found | Load `kmod-usb-acm` and reconnect the Zigbee dongle; verify with `ls -l /dev/ttyACM*`. |
| Docker fails to start due to low space | Move `/srv/zigbee2mqtt` to an external drive or free overlay space (`df -h`). |
| MQTT authentication errors | Update `mqtt_username`/`mqtt_password` via UCI and restart service. |
| Port conflict on 8080 | Change `frontend_port` in UCI, then `/etc/init.d/zigbee2mqtt restart`. |
Run `scripts/diagnose.sh` for aggregated checks (storage, cgroups, firewall sanity). Use `scripts/smoke_test.sh` to quickly start/stop the Zigbee2MQTT service and verify Docker state.
---
## Rollback / Uninstall
1. Stop and disable the service:
```sh
/etc/init.d/zigbee2mqtt stop
/etc/init.d/zigbee2mqtt disable
```
2. Remove the container image (optional):
```sh
docker rm -f secbx-zigbee2mqtt 2>/dev/null
docker rmi ghcr.io/koenkk/zigbee2mqtt:latest
```
3. Remove package:
```sh
opkg remove secubox-app-zigbee2mqtt
```
4. Clean data directory if no longer needed:
```sh
rm -rf /srv/zigbee2mqtt
```
Reinstall later by reinstalling the package and rerunning `zigbee2mqttctl install`.

85
scripts/diagnose.sh Executable file
View File

@ -0,0 +1,85 @@
#!/bin/sh
#
# SecuBox diagnostic helper.
# Checks overlay storage, cgroups availability, serial adapters,
# and basic firewall sanity for LAN/WAN zones.
set -eu
err() { printf '[ERROR] %s\n' "$*" >&2; }
warn() { printf '[WARN] %s\n' "$*" >&2; }
info() { printf '[INFO] %s\n' "$*"; }
check_storage() {
local mountpoint="/overlay"
local free
free=$(df -Pm "$mountpoint" | awk 'NR==2 {print $4}')
if [ -z "$free" ]; then
err "Unable to read storage usage for $mountpoint"
return 1
fi
info "Overlay free space: ${free}MB"
if [ "$free" -lt 100 ]; then
warn "Overlay has less than 100MB free. Consider cleaning before installing apps."
fi
}
check_cgroups() {
if [ ! -d /sys/fs/cgroup ]; then
err "cgroups are not mounted at /sys/fs/cgroup"
return 1
fi
if ! mount | grep -q 'cgroup'; then
warn "cgroups filesystem present but not mounted. Docker/LXC will fail."
else
info "cgroups mount detected."
fi
}
check_serial() {
if ls /dev/ttyACM* >/dev/null 2>&1; then
info "USB ACM device(s): $(ls /dev/ttyACM* 2>/dev/null | tr '\n' ' ')"
else
warn "No /dev/ttyACM* device detected. Plug Zigbee coordinator or load kmod-usb-acm."
fi
}
check_firewall() {
if ! command -v uci >/dev/null 2>&1; then
warn "uci not found; skipping firewall checks."
return
fi
local lan_idx
lan_idx=$(uci show firewall | grep -n "name='lan'" | head -n1 | cut -d: -f1 || true)
if [ -z "$lan_idx" ]; then
warn "Firewall LAN zone missing."
else
info "Firewall LAN zone detected."
fi
local wan_idx
wan_idx=$(uci show firewall | grep -n "name='wan'" | head -n1 | cut -d: -f1 || true)
if [ -z "$wan_idx" ]; then
warn "Firewall WAN zone missing."
else
info "Firewall WAN zone detected."
fi
}
check_docker() {
if command -v docker >/dev/null 2>&1; then
info "Docker CLI available: $(docker --version 2>/dev/null)"
else
warn "Docker CLI not found. Install dockerd/docker packages before deploying containers."
fi
}
main() {
check_storage
check_cgroups
check_serial
check_firewall
check_docker
info "Diagnostics complete."
}
main "$@"

65
scripts/smoke_test.sh Executable file
View File

@ -0,0 +1,65 @@
#!/bin/sh
#
# Basic smoke tests for SecuBox apps.
# - Verifies zigbee2mqtt service start/stop.
# - Checks Docker container health.
# - Optionally exercises MQTT pub/sub if mosquitto-clients installed.
set -eu
log() { printf '[SMOKE] %s\n' "$*"; }
err() { printf '[ERROR] %s\n' "$*" >&2; }
ensure_service() {
local svc="$1"
if [ ! -x "/etc/init.d/$svc" ]; then
err "Service $svc not installed."
return 1
fi
}
check_zigbee2mqtt() {
if ! ensure_service zigbee2mqtt; then
return
fi
log "Starting zigbee2mqtt..."
/etc/init.d/zigbee2mqtt start || return 1
sleep 3
if docker ps --filter "name=secbx-zigbee2mqtt" --format '{{.Names}}' | grep -q secbx-zigbee2mqtt; then
log "Zigbee2MQTT container is running."
else
err "Zigbee2MQTT container failed to start."
fi
log "Stopping zigbee2mqtt..."
/etc/init.d/zigbee2mqtt stop || true
}
check_mqtt_pubsub() {
if ! command -v mosquitto_pub >/dev/null 2>&1; then
log "mosquitto-clients not installed; skipping MQTT smoke test."
return
fi
local topic="secbx/smoke/test"
log "Publishing MQTT test message on $topic..."
mosquitto_pub -t "$topic" -m "smoke-test" >/dev/null 2>&1 || err "Failed to publish test message."
}
check_ports() {
local port
for port in 8080; do
if netstat -tln 2>/dev/null | grep -q ":$port "; then
log "Port $port listening."
else
log "Port $port not listening (may be expected if zigbee2mqtt is stopped)."
fi
done
}
main() {
check_zigbee2mqtt
check_mqtt_pubsub
check_ports
log "Smoke tests completed."
}
main "$@"

View File

@ -0,0 +1,42 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=secubox-app-zigbee2mqtt
PKG_RELEASE:=1
PKG_VERSION:=1.0.0
PKG_MAINTAINER:=CyberMind Studio <contact@cybermind.fr>
PKG_LICENSE:=Apache-2.0
include $(INCLUDE_DIR)/package.mk
define Package/secubox-app-zigbee2mqtt
SECTION:=utils
CATEGORY:=Utilities
SUBMENU:=SecuBox Apps
TITLE:=SecuBox Zigbee2MQTT docker app
DEPENDS:=+uci +libuci +kmod-usb-acm +bash? +dockerd +docker +containerd
endef
define Package/secubox-app-zigbee2mqtt/description
Installer, configuration, and service manager for running Zigbee2MQTT
inside Docker on SecuBox-powered OpenWrt systems.
endef
define Package/secubox-app-zigbee2mqtt/conffiles
/etc/config/zigbee2mqtt
endef
define Build/Compile
endef
define Package/secubox-app-zigbee2mqtt/install
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/zigbee2mqtt $(1)/etc/config/zigbee2mqtt
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/zigbee2mqtt $(1)/etc/init.d/zigbee2mqtt
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) ./files/usr/sbin/zigbee2mqttctl $(1)/usr/sbin/zigbee2mqttctl
endef
$(eval $(call BuildPackage,secubox-app-zigbee2mqtt))

View File

@ -0,0 +1,12 @@
config zigbee2mqtt 'main'
option enabled '0'
option image 'ghcr.io/koenkk/zigbee2mqtt:latest'
option serial_port '/dev/ttyACM0'
option mqtt_host 'mqtt://127.0.0.1:1883'
option mqtt_username ''
option mqtt_password ''
option base_topic 'zigbee2mqtt'
option frontend_port '8080'
option channel '11'
option data_path '/srv/zigbee2mqtt'
option timezone 'UTC'

View File

@ -0,0 +1,23 @@
#!/bin/sh /etc/rc.common
START=95
STOP=10
USE_PROCD=1
SERVICE_BIN="/usr/sbin/zigbee2mqttctl"
start_service() {
procd_open_instance
procd_set_param command "$SERVICE_BIN" service-run
procd_set_param respawn 2000 5 5
procd_close_instance
}
stop_service() {
"$SERVICE_BIN" service-stop >/dev/null 2>&1
}
restart_service() {
stop_service
start_service
}

View File

@ -0,0 +1,208 @@
#!/bin/sh
#
# SecuBox Zigbee2MQTT manager
# Handles prerequisite checks, Docker installation, container lifecycle,
# and configuration generation using UCI.
CONFIG="zigbee2mqtt"
CONTAINER="secbx-zigbee2mqtt"
OPKG_UPDATED=0
usage() {
cat <<'EOF'
Usage: zigbee2mqttctl <command>
Commands:
install Run prerequisite checks, install Docker packages, prepare data dir
check Validate kernel modules, cgroups, storage, and serial access
update Pull the latest Zigbee2MQTT image and restart the service
status Show container and service status
logs Show Docker logs (pass -f to follow)
service-run Internal: invoked by procd to run the container
service-stop Stop the running container
help Show this message
EOF
}
require_root() {
if [ "$(id -u)" -ne 0 ]; then
echo "This command requires root privileges." >&2
exit 1
fi
}
uci_get() {
uci -q get "${CONFIG}.main.$1"
}
defaults() {
serial_port="$(uci_get serial_port || echo /dev/ttyACM0)"
mqtt_host="$(uci_get mqtt_host || echo mqtt://127.0.0.1:1883)"
mqtt_user="$(uci_get mqtt_username || printf '')"
mqtt_pass="$(uci_get mqtt_password || printf '')"
base_topic="$(uci_get base_topic || echo zigbee2mqtt)"
frontend_port="$(uci_get frontend_port || echo 8080)"
channel="$(uci_get channel || echo 11)"
image="$(uci_get image || echo ghcr.io/koenkk/zigbee2mqtt:latest)"
data_path="$(uci_get data_path || echo /srv/zigbee2mqtt)"
timezone="$(uci_get timezone || echo UTC)"
}
ensure_dir() {
local path="$1"
[ -d "$path" ] || mkdir -p "$path"
}
ensure_packages() {
local pkgs="$*"
require_root
for pkg in $pkgs; do
if ! opkg status "$pkg" >/dev/null 2>&1; then
if [ "$OPKG_UPDATED" -eq 0 ]; then
opkg update || return 1
OPKG_UPDATED=1
fi
opkg install "$pkg" || return 1
fi
done
return 0
}
check_storage() {
local target="$1"
local free_kb
free_kb=$(df -Pk "${target:-/overlay}" | awk 'NR==2 {print $4}')
[ -z "$free_kb" ] && free_kb=0
if [ "$free_kb" -lt 102400 ]; then
echo "[WARN] Less than 100MB free on ${target:-overlay}. Docker images may fail." >&2
fi
}
check_cgroups() {
if [ ! -d /sys/fs/cgroup ]; then
echo "[ERROR] /sys/fs/cgroup missing. Enable cgroups in the kernel." >&2
return 1
fi
return 0
}
check_serial() {
local port="$1"
if [ ! -c "$port" ]; then
echo "[WARN] Serial device $port not found. Plug the Zigbee coordinator first." >&2
fi
}
check_prereqs() {
defaults
check_storage "$data_path"
check_cgroups || return 1
check_serial "$serial_port"
ensure_packages kmod-usb-acm || return 1
return 0
}
ensure_docker() {
ensure_packages containerd docker dockerd || return 1
/etc/init.d/dockerd enable >/dev/null 2>&1
/etc/init.d/dockerd start >/dev/null 2>&1
}
generate_configuration() {
defaults
ensure_dir "$data_path/data"
cat > "$data_path/data/configuration.yaml" <<EOF
homeassistant: true
permit_join: false
mqtt:
base_topic: "${base_topic}"
server: "${mqtt_host}"
user: "${mqtt_user}"
password: "${mqtt_pass}"
serial:
port: "${serial_port}"
advanced:
channel: ${channel}
frontend:
port: ${frontend_port}
EOF
chmod 600 "$data_path/data/configuration.yaml"
}
pull_image() {
defaults
docker pull "$image"
}
stop_container() {
docker stop "$CONTAINER" >/dev/null 2>&1 || true
docker rm "$CONTAINER" >/dev/null 2>&1 || true
}
cmd_install() {
require_root
check_prereqs || exit 1
ensure_docker || exit 1
ensure_dir "$data_path"
generate_configuration
pull_image
/etc/init.d/zigbee2mqtt enable
echo "Zigbee2MQTT prerequisites installed. Enable with: /etc/init.d/zigbee2mqtt start"
}
cmd_check() {
check_prereqs
echo "Prerequisite check completed."
}
cmd_update() {
require_root
defaults
pull_image || exit 1
if /etc/init.d/zigbee2mqtt enabled >/dev/null 2>&1; then
/etc/init.d/zigbee2mqtt restart
else
echo "Image updated. Restart manually to apply."
fi
}
cmd_status() {
docker ps -a --filter "name=$CONTAINER"
}
cmd_logs() {
docker logs "$@" "$CONTAINER"
}
cmd_service_run() {
require_root
check_prereqs || exit 1
ensure_docker || exit 1
generate_configuration
stop_container
defaults
exec docker run --rm \
--name "$CONTAINER" \
--device "$serial_port" \
-p "${frontend_port}:8080" \
-v "$data_path/data:/app/data" \
-e TZ="$timezone" \
"$image"
}
cmd_service_stop() {
require_root
stop_container
}
case "$1" in
install) shift; cmd_install "$@";;
check) shift; cmd_check "$@";;
update) shift; cmd_update "$@";;
status) shift; cmd_status "$@";;
logs) shift; cmd_logs "$@";;
service-run) shift; cmd_service_run "$@";;
service-stop) shift; cmd_service_stop "$@";;
help|--help|-h|"") usage;;
*) echo "Unknown command: $1" >&2; usage >&2; exit 1;;
esac