config.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package main
  2. import (
  3. "encoding/json"
  4. "os"
  5. "path/filepath"
  6. )
  7. // Config holds the daemon configuration
  8. type Config struct {
  9. // Mode: "cloud" (server settings priority) or "lan" (local settings priority)
  10. Mode string `json:"mode"`
  11. // Server settings
  12. APIBase string `json:"api_base"`
  13. // Device identity (persisted)
  14. DeviceID string `json:"device_id,omitempty"`
  15. DeviceToken string `json:"device_token,omitempty"`
  16. // BLE settings
  17. BLE struct {
  18. Enabled bool `json:"enabled"`
  19. BatchIntervalMs int `json:"batch_interval_ms"`
  20. } `json:"ble"`
  21. // WiFi settings
  22. WiFi struct {
  23. MonitorEnabled bool `json:"monitor_enabled"`
  24. ClientEnabled bool `json:"client_enabled"`
  25. SSID string `json:"ssid"`
  26. PSK string `json:"psk"`
  27. BatchIntervalMs int `json:"batch_interval_ms"`
  28. } `json:"wifi"`
  29. // SSH Tunnel settings
  30. SSHTunnel struct {
  31. Enabled bool `json:"enabled"`
  32. Server string `json:"server"`
  33. Port int `json:"port"`
  34. User string `json:"user"`
  35. KeyPath string `json:"key_path"`
  36. RemotePort int `json:"remote_port"`
  37. KeepaliveInterval int `json:"keepalive_interval"`
  38. ReconnectDelay int `json:"reconnect_delay"`
  39. } `json:"ssh_tunnel"`
  40. // Network settings (eth0 is ALWAYS local, never from server)
  41. Network struct {
  42. NTPServers []string `json:"ntp_servers"`
  43. Eth0 struct {
  44. Static bool `json:"static"`
  45. Address string `json:"address"`
  46. Gateway string `json:"gateway"`
  47. DNS string `json:"dns"`
  48. } `json:"eth0"`
  49. } `json:"network"`
  50. // Local-only settings (never from server)
  51. ZMQAddrBLE string `json:"zmq_addr_ble"`
  52. ZMQAddrWiFi string `json:"zmq_addr_wifi"`
  53. SpoolDir string `json:"spool_dir"`
  54. WiFiIface string `json:"wifi_iface"`
  55. Debug bool `json:"debug"`
  56. }
  57. // DefaultConfig returns a configuration with default values
  58. func DefaultConfig() *Config {
  59. cfg := &Config{
  60. Mode: "cloud",
  61. APIBase: "http://localhost:5000/api/v1",
  62. ZMQAddrBLE: "tcp://127.0.0.1:5555",
  63. ZMQAddrWiFi: "tcp://127.0.0.1:5556",
  64. SpoolDir: "/var/spool/mybeacon",
  65. }
  66. cfg.BLE.Enabled = true
  67. cfg.BLE.BatchIntervalMs = 2500
  68. cfg.WiFi.MonitorEnabled = false
  69. cfg.WiFi.BatchIntervalMs = 10000
  70. cfg.SSHTunnel.Port = 22
  71. cfg.SSHTunnel.KeepaliveInterval = 30
  72. cfg.SSHTunnel.ReconnectDelay = 5
  73. cfg.Network.NTPServers = []string{"pool.ntp.org"}
  74. return cfg
  75. }
  76. // LoadConfig loads configuration from a JSON file
  77. func LoadConfig(path string) (*Config, error) {
  78. cfg := DefaultConfig()
  79. data, err := os.ReadFile(path)
  80. if err != nil {
  81. if os.IsNotExist(err) {
  82. return cfg, nil // Use defaults
  83. }
  84. return nil, err
  85. }
  86. if err := json.Unmarshal(data, cfg); err != nil {
  87. return nil, err
  88. }
  89. return cfg, nil
  90. }
  91. // SaveConfig saves configuration to a JSON file
  92. func SaveConfig(path string, cfg *Config) error {
  93. dir := filepath.Dir(path)
  94. if err := os.MkdirAll(dir, 0755); err != nil {
  95. return err
  96. }
  97. data, err := json.MarshalIndent(cfg, "", " ")
  98. if err != nil {
  99. return err
  100. }
  101. return os.WriteFile(path, data, 0600)
  102. }
  103. // DeviceState holds persistent device state
  104. type DeviceState struct {
  105. DeviceID string `json:"device_id"`
  106. DeviceToken string `json:"device_token"`
  107. DevicePassword string `json:"device_password,omitempty"`
  108. }
  109. // LoadDeviceState loads device state from file
  110. func LoadDeviceState(path string) (*DeviceState, error) {
  111. state := &DeviceState{}
  112. data, err := os.ReadFile(path)
  113. if err != nil {
  114. if os.IsNotExist(err) {
  115. return state, nil
  116. }
  117. return nil, err
  118. }
  119. if err := json.Unmarshal(data, state); err != nil {
  120. return nil, err
  121. }
  122. return state, nil
  123. }
  124. // SaveDeviceState saves device state to file
  125. func SaveDeviceState(path string, state *DeviceState) error {
  126. dir := filepath.Dir(path)
  127. if err := os.MkdirAll(dir, 0755); err != nil {
  128. return err
  129. }
  130. data, err := json.MarshalIndent(state, "", " ")
  131. if err != nil {
  132. return err
  133. }
  134. return os.WriteFile(path, data, 0600)
  135. }