package main import ( "encoding/hex" "net" "time" ) // 传感器通信相关结构和函数 type SensorComm struct { conn net.Conn address string lastQueryTime time.Time lastResetTime time.Time querySuccess bool responseRecv chan bool queryCmd []byte resetCmd []byte } // 创建新的传感器通信实例 func newSensorComm(conn net.Conn) *SensorComm { sc := &SensorComm{ conn: conn, address: conn.RemoteAddr().String(), lastQueryTime: time.Time{}, lastResetTime: time.Time{}, querySuccess: false, responseRecv: make(chan bool, 1), // 带缓冲的通道,避免阻塞 queryCmd: prepareQueryCommand(), resetCmd: prepareResetCommand(), } return sc } // 准备查询命令 func prepareQueryCommand() []byte { queryHexData := "01 03 01 F4 00 10 04 08" queryHexData = removeSpaces(queryHexData) queryData, err := hex.DecodeString(queryHexData) if err != nil { logger.Printf("解析查询命令错误: %v", err) return nil } return queryData } // 准备重置命令 func prepareResetCommand() []byte { resetHexData := "01 06 60 02 00 5A B6 31" resetHexData = removeSpaces(resetHexData) resetData, err := hex.DecodeString(resetHexData) if err != nil { logger.Printf("解析重置命令错误: %v", err) return nil } return resetData } // 发送查询命令 func (sc *SensorComm) sendQuery() bool { sc.querySuccess = false _, err := sc.conn.Write(sc.queryCmd) if err != nil { logger.Printf("发送查询命令错误: %v", err) return false } sc.lastQueryTime = time.Now() logger.Printf("发送查询命令: %s", time.Now().Format("15:04:05")) return true } // 发送整点重置命令,在重置前先查询保存数据 func (sc *SensorComm) resetHourly() bool { if time.Since(sc.lastResetTime) < 5*time.Minute { logger.Printf("最近5分钟内已重置过雨量,跳过本次重置") return false } sc.querySuccess = false _, err := sc.conn.Write(sc.queryCmd) if err != nil { logger.Printf("重置前查询命令错误: %v", err) // 继续执行重置,不因查询失败而中断重置 } else { logger.Printf("重置前发送查询命令: %s", time.Now().Format("15:04:05")) // 等待一小段时间确保查询完成并且数据被处理 time.Sleep(2000 * time.Millisecond) } // 发送重置命令 _, err = sc.conn.Write(sc.resetCmd) if err != nil { logger.Printf("发送重置命令错误: %v", err) return false } logger.Printf("发送雨量重置命令: %s", time.Now().Format("15:04:05")) sc.lastResetTime = time.Now() return true } // 处理接收到的数据 func (sc *SensorComm) handleData(data []byte) *SensorData { sensorData := parseData(data) if sensorData != nil { sc.querySuccess = true // 通知已收到响应 select { case sc.responseRecv <- true: default: // 通道已满或无接收者,这里不阻塞 } return sensorData } return nil } // 关闭连接 func (sc *SensorComm) close() { if sc.conn != nil { sc.conn.Close() } close(sc.responseRecv) } // 移除字符串中的空格 func removeSpaces(s string) string { var result []rune for _, r := range s { if r != ' ' { result = append(result, r) } } return string(result) }