| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- package main
- import (
- "encoding/json"
- "os"
- "path/filepath"
- )
- // Config holds the daemon configuration
- type Config struct {
- // Mode: "cloud" (server settings priority) or "lan" (local settings priority)
- Mode string `json:"mode"`
- // Server settings
- APIBase string `json:"api_base"`
- // Device identity (persisted)
- DeviceID string `json:"device_id,omitempty"`
- DeviceToken string `json:"device_token,omitempty"`
- // BLE settings
- BLE struct {
- Enabled bool `json:"enabled"`
- BatchIntervalMs int `json:"batch_interval_ms"`
- } `json:"ble"`
- // WiFi settings
- WiFi struct {
- MonitorEnabled bool `json:"monitor_enabled"`
- ClientEnabled bool `json:"client_enabled"`
- SSID string `json:"ssid"`
- PSK string `json:"psk"`
- BatchIntervalMs int `json:"batch_interval_ms"`
- } `json:"wifi"`
- // SSH Tunnel settings (for terminal access)
- SSHTunnel struct {
- Enabled bool `json:"enabled"`
- Server string `json:"server"`
- Port int `json:"port"`
- User string `json:"user"`
- KeyPath string `json:"key_path"`
- RemotePort int `json:"remote_port"`
- KeepaliveInterval int `json:"keepalive_interval"`
- ReconnectDelay int `json:"reconnect_delay"`
- } `json:"ssh_tunnel"`
- // Dashboard Tunnel settings (for web dashboard access)
- DashboardTunnel struct {
- Enabled bool `json:"enabled"`
- Server string `json:"server"`
- Port int `json:"port"`
- User string `json:"user"`
- RemotePort int `json:"remote_port"`
- KeepaliveInterval int `json:"keepalive_interval"`
- ReconnectDelay int `json:"reconnect_delay"`
- } `json:"dashboard_tunnel"`
- // Network settings (eth0 is ALWAYS local, never from server)
- Network struct {
- NTPServers []string `json:"ntp_servers"`
- Eth0 struct {
- Static bool `json:"static"`
- Address string `json:"address"`
- Gateway string `json:"gateway"`
- DNS string `json:"dns"`
- } `json:"eth0"`
- } `json:"network"`
- // AP Fallback settings (when no network available for 120s)
- APFallback struct {
- Password string `json:"password"` // Default: "mybeacon123"
- } `json:"ap_fallback"`
- // Dashboard settings
- Dashboard struct {
- Enabled bool `json:"enabled"`
- } `json:"dashboard"`
- // Local-only settings (never from server)
- ZMQAddrBLE string `json:"zmq_addr_ble"`
- ZMQAddrWiFi string `json:"zmq_addr_wifi"`
- SpoolDir string `json:"spool_dir"`
- WiFiIface string `json:"wifi_iface"`
- Debug bool `json:"debug"`
- }
- // DefaultConfig returns a configuration with default values
- func DefaultConfig() *Config {
- cfg := &Config{
- Mode: "cloud",
- APIBase: "http://localhost:5000/api/v1",
- ZMQAddrBLE: "tcp://127.0.0.1:5555",
- ZMQAddrWiFi: "tcp://127.0.0.1:5556",
- SpoolDir: "/var/spool/mybeacon",
- }
- cfg.BLE.Enabled = true
- cfg.BLE.BatchIntervalMs = 2500
- cfg.WiFi.MonitorEnabled = false
- cfg.WiFi.BatchIntervalMs = 10000
- cfg.SSHTunnel.Port = 22
- cfg.SSHTunnel.KeepaliveInterval = 30
- cfg.SSHTunnel.ReconnectDelay = 5
- cfg.DashboardTunnel.Port = 22
- cfg.DashboardTunnel.KeepaliveInterval = 30
- cfg.DashboardTunnel.ReconnectDelay = 5
- cfg.Network.NTPServers = []string{"pool.ntp.org"}
- cfg.APFallback.Password = "mybeacon"
- cfg.Dashboard.Enabled = true
- return cfg
- }
- // LoadConfig loads configuration from a JSON file
- func LoadConfig(path string) (*Config, error) {
- cfg := DefaultConfig()
- data, err := os.ReadFile(path)
- if err != nil {
- if os.IsNotExist(err) {
- return cfg, nil // Use defaults
- }
- return nil, err
- }
- if err := json.Unmarshal(data, cfg); err != nil {
- return nil, err
- }
- return cfg, nil
- }
- // SaveConfig saves configuration to a JSON file
- func SaveConfig(path string, cfg *Config) error {
- dir := filepath.Dir(path)
- if err := os.MkdirAll(dir, 0755); err != nil {
- return err
- }
- data, err := json.MarshalIndent(cfg, "", " ")
- if err != nil {
- return err
- }
- return os.WriteFile(path, data, 0600)
- }
- // DeviceState holds persistent device state
- type DeviceState struct {
- DeviceID string `json:"device_id"`
- DeviceToken string `json:"device_token"`
- DevicePassword string `json:"device_password,omitempty"`
- }
- // LoadDeviceState loads device state from file
- func LoadDeviceState(path string) (*DeviceState, error) {
- state := &DeviceState{}
- data, err := os.ReadFile(path)
- if err != nil {
- if os.IsNotExist(err) {
- return state, nil
- }
- return nil, err
- }
- if err := json.Unmarshal(data, state); err != nil {
- return nil, err
- }
- return state, nil
- }
- // SaveDeviceState saves device state to file
- func SaveDeviceState(path string, state *DeviceState) error {
- dir := filepath.Dir(path)
- if err := os.MkdirAll(dir, 0755); err != nil {
- return err
- }
- data, err := json.MarshalIndent(state, "", " ")
- if err != nil {
- return err
- }
- return os.WriteFile(path, data, 0600)
- }
|