242 lines
6.6 KiB
Go
242 lines
6.6 KiB
Go
package main
|
|
|
|
import (
|
|
"Dynamic_environmental_detection/business"
|
|
"Dynamic_environmental_detection/connect"
|
|
"Dynamic_environmental_detection/logger"
|
|
"encoding/json"
|
|
"flag"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
// 解析命令行参数
|
|
debugMode := flag.Bool("debug", false, "Enable debug mode")
|
|
slaveID := flag.String("slave", "2", "Slave address (debug mode only)")
|
|
sensorType := flag.String("type", "1", "Sensor type 1-Temperature/Humidity, 2-Water Leak, 3-Smoke (debug mode only)")
|
|
rawCommand := flag.String("cmd", "", "Raw Modbus command (hexadecimal, debug mode only)")
|
|
flag.Parse()
|
|
|
|
// 初始化日志
|
|
if err := logger.InitLogger(); err != nil {
|
|
log.Fatal("Failed to initialize logger:", err)
|
|
}
|
|
defer logger.Close()
|
|
|
|
// 调试模式
|
|
if *debugMode {
|
|
runDebugMode(*slaveID, *sensorType, *rawCommand)
|
|
return
|
|
}
|
|
|
|
// 正常模式
|
|
runNormalMode()
|
|
}
|
|
|
|
// runDebugMode 运行调试模式
|
|
func runDebugMode(slaveID, sensorType, rawCommand string) {
|
|
logger.Logger.Printf("=== Environmental Detection System Debug Mode ===")
|
|
|
|
debugHandler := business.NewDebugHandler()
|
|
|
|
if rawCommand != "" {
|
|
// 原始命令模式
|
|
if err := debugHandler.TestRawCommand(rawCommand); err != nil {
|
|
logger.Logger.Printf("Debug failed: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
} else {
|
|
// 设备测试模式
|
|
if err := debugHandler.TestDevice(slaveID, sensorType); err != nil {
|
|
logger.Logger.Printf("Debug failed: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// setupGracefulShutdown 设置优雅关闭
|
|
func setupGracefulShutdown() {
|
|
sigChan := make(chan os.Signal, 1)
|
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
sig := <-sigChan
|
|
logger.Logger.Printf("Received signal: %v, starting shutdown", sig)
|
|
|
|
// 关闭 WebSocket 连接
|
|
connect.Close()
|
|
logger.Logger.Printf("WebSocket connection closed")
|
|
|
|
logger.Logger.Printf("=== System exited ===")
|
|
os.Exit(0)
|
|
}()
|
|
}
|
|
|
|
// runNormalMode 运行正常模式
|
|
func runNormalMode() {
|
|
logger.Logger.Printf("=== Environmental Detection System Starting ===")
|
|
|
|
// 原有的正常模式代码...
|
|
// 2. 初始化 WebSocket 连接
|
|
logger.Logger.Printf("Initializing WebSocket connection...")
|
|
if err := connect.InitWSChannel(); err != nil {
|
|
log.Fatal("WebSocket connection initialization failed:", err)
|
|
}
|
|
|
|
// 3. 解析配置文件
|
|
logger.Logger.Printf("Parsing sensor configuration file...")
|
|
configs, err := business.ParseServiceConfig("/usr/local/etc/service.conf")
|
|
if err != nil {
|
|
log.Fatal("Configuration parsing failed:", err)
|
|
}
|
|
|
|
// 4. 验证配置
|
|
if err := business.ValidateConfig(configs); err != nil {
|
|
log.Fatal("Configuration validation failed:", err)
|
|
}
|
|
|
|
// 5. 注册服务
|
|
logger.Logger.Printf("Registering service to server...")
|
|
serviceID := connect.GenerateServiceID()
|
|
metaData := map[string]interface{}{
|
|
"version": "1.0",
|
|
"type": "environment_detection",
|
|
"sensor_count": len(configs),
|
|
"description": "Environmental Detection Service",
|
|
}
|
|
|
|
if err := connect.RegisterService(serviceID, metaData, "environment-detection-container"); err != nil {
|
|
log.Fatal("Service registration failed:", err)
|
|
}
|
|
|
|
// 6. 创建业务管理器
|
|
logger.Logger.Printf("Creating business manager...")
|
|
businessManager, err := business.NewBusinessManager(configs)
|
|
if err != nil {
|
|
log.Fatal("Failed to create business manager:", err)
|
|
}
|
|
defer businessManager.Close()
|
|
|
|
// 7. 订阅主题处理服务器消息
|
|
logger.Logger.Printf("Subscribing to device updates topic...")
|
|
if err := connect.SubscribeTopic("device_updates", handleDeviceUpdates); err != nil {
|
|
log.Fatal("Topic subscription failed:", err)
|
|
}
|
|
logger.Logger.Printf("Subscribing to alert topic (/dthjjc/alert) for buzzer...")
|
|
|
|
if err := connect.SubscribeTopic("/dthjjc/alert", handleAlertMessage); err != nil {
|
|
logger.Logger.Printf("Failed to subscribe alert topic: %v (continue anyway)", err)
|
|
} else {
|
|
logger.Logger.Printf("Successfully subscribed to /dthjjc/alert → buzzer ready!")
|
|
}
|
|
|
|
// 8. 启动数据采集循环
|
|
logger.Logger.Printf("Starting data collection loop...")
|
|
go startDataCollectionLoop(businessManager)
|
|
|
|
// 9. 设置优雅关闭
|
|
setupGracefulShutdown()
|
|
|
|
logger.Logger.Printf("=== System startup completed, beginning operation ===")
|
|
|
|
// 永久运行
|
|
select {}
|
|
}
|
|
|
|
// handleDeviceUpdates 处理设备更新消息
|
|
func handleDeviceUpdates(params *connect.PublishParams) {
|
|
logger.Logger.Printf("Received device update message, topic: %s", params.Topic)
|
|
|
|
var updateData map[string]interface{}
|
|
if err := json.Unmarshal(params.Data, &updateData); err != nil {
|
|
logger.Logger.Printf("Failed to parse device update message: %v", err)
|
|
return
|
|
}
|
|
|
|
logger.Logger.Printf("Device update content: %+v", updateData)
|
|
}
|
|
|
|
// startDataCollectionLoop 启动数据采集循环
|
|
func startDataCollectionLoop(businessManager *business.BusinessManager) {
|
|
|
|
collectionInterval := 20 * time.Second
|
|
ticker := time.NewTicker(collectionInterval)
|
|
defer ticker.Stop()
|
|
logger.Logger.Printf("Data collection loop started, interval: %v", collectionInterval)
|
|
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
if err := businessManager.StartDataCollection(); err != nil {
|
|
logger.Logger.Printf("Data collection failed: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func handleAlertMessage(params *connect.PublishParams) {
|
|
payload := params.Content
|
|
if len(payload) == 0 {
|
|
payload = params.Data
|
|
}
|
|
if len(payload) == 0 {
|
|
logger.Logger.Printf("平台告警空包 → 强制响 3 秒")
|
|
business.TriggerBuzzer(3)
|
|
return
|
|
}
|
|
|
|
raw := string(payload)
|
|
logger.Logger.Printf("收到告警原始内容 → %s", raw)
|
|
|
|
type Cmd struct {
|
|
Type int `json:"type"`
|
|
BuzzerDuration json.RawMessage `json:"buzzer_duration"` // 万能类型!
|
|
}
|
|
var cmd Cmd
|
|
|
|
var outer string
|
|
if json.Unmarshal(payload, &outer) == nil {
|
|
logger.Logger.Printf("检测到外层是字符串 → %s", outer)
|
|
raw = outer
|
|
}
|
|
|
|
if err := json.Unmarshal([]byte(raw), &cmd); err != nil {
|
|
logger.Logger.Printf("最终解析失败: %v → 暴力识别", err)
|
|
} else if cmd.Type == 1 {
|
|
|
|
dur := 3
|
|
var temp interface{}
|
|
if json.Unmarshal(cmd.BuzzerDuration, &temp) == nil {
|
|
switch v := temp.(type) {
|
|
case string:
|
|
if n, err := strconv.Atoi(v); err == nil {
|
|
dur = n
|
|
}
|
|
case float64:
|
|
dur = int(v)
|
|
case int:
|
|
dur = v
|
|
}
|
|
}
|
|
if dur <= 0 {
|
|
dur = 3
|
|
}
|
|
|
|
logger.Logger.Printf("平台告警解析成功 → 蜂鸣器响 %d 秒!!!", dur)
|
|
business.TriggerBuzzer(dur)
|
|
return
|
|
}
|
|
|
|
// 终极兜底:只要包含 type 和 1 就响
|
|
//if strings.Contains(raw, "type") && strings.Contains(raw, "1") {
|
|
// logger.Logger.Printf("暴力识别告警指令 → 强制响 3 秒")
|
|
// business.TriggerBuzzer(3)
|
|
//}
|
|
}
|