go_rain_dtu/sensor_comm.go
2025-05-14 16:56:03 +08:00

141 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}