feat: scheduled auto-sync for Zigbee & Z-Wave imports
Mirror the Proxmox auto-sync pattern for the Zigbee2MQTT and Z-Wave JS UI mesh imports. Connection config + MQTT credentials live in .env only, are never persisted to scan_config.json, and are never returned by any API or shown in the UI (single source of truth). - config: ZIGBEE_* / ZWAVE_* env settings; only sync_enabled+interval are persisted, connection/credentials stay env-only - routes: GET/POST /config, POST /sync-now; auto-sync reuses the exact manual _background_*_import + _persist_pending_import path (fresh import when empty, update-in-place when nodes exist, ScanRun trace) - scheduler: zigbee_sync / zwave_sync jobs with live enable + reschedule - frontend: reusable MeshAutoSync section in Settings (Zigbee, Z-Wave) - .env.example: documented both blocks - tests: scheduler jobs, router config/sync-now/auth, credential-never- persisted, SettingsModal sections Manual Zigbee/Z-Wave import behaviour is unchanged. ha-relevant: no
This commit is contained in:
@@ -211,6 +211,39 @@ export const designsApi = {
|
||||
delete: (id: string) => api.delete(`/designs/${id}`),
|
||||
}
|
||||
|
||||
export interface ZigbeeConfigData {
|
||||
mqtt_host: string
|
||||
mqtt_port: number
|
||||
base_topic: string
|
||||
mqtt_tls: boolean
|
||||
sync_enabled: boolean
|
||||
sync_interval: number
|
||||
host_configured: boolean
|
||||
}
|
||||
|
||||
export interface ZwaveConfigData {
|
||||
mqtt_host: string
|
||||
mqtt_port: number
|
||||
prefix: string
|
||||
gateway_name: string
|
||||
mqtt_tls: boolean
|
||||
sync_enabled: boolean
|
||||
sync_interval: number
|
||||
host_configured: boolean
|
||||
}
|
||||
|
||||
// Shape returned by every background-scan trigger (import-pending / sync-now).
|
||||
interface ScanRunResult {
|
||||
id: string
|
||||
status: string
|
||||
kind: string
|
||||
ranges: string[]
|
||||
devices_found: number
|
||||
started_at: string
|
||||
finished_at: string | null
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export const zigbeeApi = {
|
||||
testConnection: (data: {
|
||||
mqtt_host: string
|
||||
@@ -256,6 +289,13 @@ export const zigbeeApi = {
|
||||
finished_at: string | null
|
||||
error: string | null
|
||||
}>('/zigbee/import-pending', data),
|
||||
|
||||
getConfig: () => api.get<ZigbeeConfigData>('/zigbee/config'),
|
||||
// Only the auto-sync activation is persisted. MQTT connection config
|
||||
// (host/port/credentials/topic/tls) is env-only and never sent.
|
||||
saveConfig: (data: { sync_enabled: boolean; sync_interval: number }) =>
|
||||
api.post<ZigbeeConfigData>('/zigbee/config', data),
|
||||
syncNow: () => api.post<ScanRunResult>('/zigbee/sync-now'),
|
||||
}
|
||||
|
||||
export const zwaveApi = {
|
||||
@@ -305,4 +345,11 @@ export const zwaveApi = {
|
||||
finished_at: string | null
|
||||
error: string | null
|
||||
}>('/zwave/import-pending', data),
|
||||
|
||||
getConfig: () => api.get<ZwaveConfigData>('/zwave/config'),
|
||||
// Only the auto-sync activation is persisted. MQTT connection config
|
||||
// (host/port/credentials/prefix/gateway/tls) is env-only and never sent.
|
||||
saveConfig: (data: { sync_enabled: boolean; sync_interval: number }) =>
|
||||
api.post<ZwaveConfigData>('/zwave/config', data),
|
||||
syncNow: () => api.post<ScanRunResult>('/zwave/sync-now'),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user