feat: bootstrap zigbee2mqtt app and diagnostics
This commit is contained in:
parent
d566a84dda
commit
ec81952db1
110
DOCS/ARCHITECTURE_NOTES.md
Normal file
110
DOCS/ARCHITECTURE_NOTES.md
Normal 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; don’t 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.
|
||||
@ -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*
|
||||
|
||||
7
DOCS/embedded/docker-zigbee2mqtt.md
Normal file
7
DOCS/embedded/docker-zigbee2mqtt.md
Normal 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.
|
||||
7
docs/ARCHITECTURE_NOTES.md
Normal file
7
docs/ARCHITECTURE_NOTES.md
Normal 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.
|
||||
@ -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*
|
||||
|
||||
115
docs/embedded/docker-zigbee2mqtt.md
Normal file
115
docs/embedded/docker-zigbee2mqtt.md
Normal 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 200 MB 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
85
scripts/diagnose.sh
Executable 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
65
scripts/smoke_test.sh
Executable 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 "$@"
|
||||
42
secubox-app-zigbee2mqtt/Makefile
Normal file
42
secubox-app-zigbee2mqtt/Makefile
Normal 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))
|
||||
12
secubox-app-zigbee2mqtt/files/etc/config/zigbee2mqtt
Normal file
12
secubox-app-zigbee2mqtt/files/etc/config/zigbee2mqtt
Normal 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'
|
||||
23
secubox-app-zigbee2mqtt/files/etc/init.d/zigbee2mqtt
Normal file
23
secubox-app-zigbee2mqtt/files/etc/init.d/zigbee2mqtt
Normal 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
|
||||
}
|
||||
208
secubox-app-zigbee2mqtt/files/usr/sbin/zigbee2mqttctl
Normal file
208
secubox-app-zigbee2mqtt/files/usr/sbin/zigbee2mqttctl
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user