// Package config 加载 IoT Server 的 MQTT、协议密钥和内部接口配置。 package config import ( "encoding/hex" "fmt" "os" "strings" "gopkg.in/yaml.v3" ) type MQTT struct { Address string `yaml:"Address"` ListenerID string `yaml:"ListenerID"` Devices []MQTTDevice `yaml:"Devices"` UpTopic string `yaml:"UpTopic"` DownTopic string `yaml:"DownTopic"` AckTopic string `yaml:"AckTopic"` QoS byte `yaml:"QoS"` TLS bool `yaml:"TLS"` CAFile string `yaml:"CAFile"` CertificateFile string `yaml:"CertificateFile"` PrivateKeyFile string `yaml:"PrivateKeyFile"` } type MQTTDevice struct { ClientID string `yaml:"ClientID"` DeviceID string `yaml:"DeviceID"` Username string `yaml:"Username"` Password string `yaml:"Password"` } type HTTP struct { Address string `yaml:"Address"` InternalToken string `yaml:"InternalToken"` CallbackURL string `yaml:"CallbackURL"` } type Protocol struct { Key1 string `yaml:"Key1"` Key2 string `yaml:"Key2"` Key3 string `yaml:"Key3"` } type Config struct { Service string `yaml:"Service"` MQTT MQTT `yaml:"MQTT"` HTTP HTTP `yaml:"HTTP"` Protocol Protocol `yaml:"Protocol"` } func Load(path string) (Config, error) { var cfg Config data, err := os.ReadFile(path) if err != nil { return cfg, err } if err = yaml.Unmarshal(data, &cfg); err != nil { return cfg, err } if len(cfg.MQTT.Devices) == 1 { override(&cfg.MQTT.Devices[0].Password, "HEQI_IOT_MQTT_PASSWORD") } override(&cfg.HTTP.InternalToken, "HEQI_IOT_INTERNAL_TOKEN") override(&cfg.Protocol.Key1, "HEQI_IOT_KEY_1") override(&cfg.Protocol.Key2, "HEQI_IOT_KEY_2") override(&cfg.Protocol.Key3, "HEQI_IOT_KEY_3") if cfg.MQTT.Address == "" || cfg.HTTP.Address == "" || cfg.HTTP.InternalToken == "" { return cfg, fmt.Errorf("MQTT.Address、HTTP.Address 和 HTTP.InternalToken 必填") } if cfg.MQTT.ListenerID == "" { cfg.MQTT.ListenerID = "mqtt-tcp" } if len(cfg.MQTT.Devices) == 0 { return cfg, fmt.Errorf("MQTT.Devices 必填,Broker 禁止匿名连接") } for index, device := range cfg.MQTT.Devices { if device.ClientID == "" || device.DeviceID == "" || device.Username == "" || device.Password == "" { return cfg, fmt.Errorf("MQTT.Devices[%d] 的 ClientID、DeviceID、Username 和 Password 必填", index) } } return cfg, nil } func (cfg Config) Keys() (map[byte][]byte, error) { result := map[byte][]byte{} for id, value := range map[byte]string{1: cfg.Protocol.Key1, 2: cfg.Protocol.Key2, 3: cfg.Protocol.Key3} { if strings.TrimSpace(value) == "" { continue } decoded, err := hex.DecodeString(value) if err != nil || len(decoded) != 16 { return nil, fmt.Errorf("Protocol.Key%d 必须是 32 位十六进制 AES-128 密钥", id) } result[id] = decoded } return result, nil } func override(target *string, name string) { if value := os.Getenv(name); value != "" { *target = value } }