feat: 新增 485 的解析

This commit is contained in:
yarnom 2025-08-03 14:01:09 +08:00
parent 6e643497a1
commit 419a5c940e
2 changed files with 213 additions and 66 deletions

201
main.go
View File

@ -130,18 +130,61 @@ func startUDP() {
// 检查数据是否为RS485格式 // 检查数据是否为RS485格式
if len(rawData) == 25 && rawData[0] == 0x24 { if len(rawData) == 25 && rawData[0] == 0x24 {
log.Println("=== 检测到RS485设备数据 ===")
// 生成源码字符串(用于日志记录)
sourceHex := strings.ReplaceAll(strings.TrimSpace(hexDump), "\n", " ")
log.Printf("源码: %s", sourceHex)
// 解析RS485数据 // 解析RS485数据
hexStr := strings.ReplaceAll(hexDump, "\n", " ") protocol := model.NewProtocol(rawData)
parseHexData(hexStr) rs485Protocol := model.NewRS485Protocol(rawData)
// 获取设备ID
idParts, err := protocol.GetCompleteID()
if err != nil {
log.Printf("获取设备ID失败: %v", err)
continue
}
// 解析RS485数据
rs485Data, err := rs485Protocol.ParseRS485Data()
if err != nil {
log.Printf("解析RS485数据失败: %v", err)
continue
}
// 添加设备ID和时间戳
rs485Data.DeviceID = idParts.Complete.Hex
rs485Data.ReceivedAt = time.Now()
rs485Data.RawDataHex = sourceHex
// 打印解析结果到日志
log.Println("=== RS485解析结果 ===")
log.Printf("设备ID: RS485-%s", rs485Data.DeviceID)
log.Printf("温度: %.2f°C", rs485Data.Temperature)
log.Printf("湿度: %.1f%%", rs485Data.Humidity)
log.Printf("风速: %.5f m/s", rs485Data.WindSpeed)
log.Printf("风向: %.1f°", rs485Data.WindDirection)
log.Printf("降雨量: %.3f mm", rs485Data.Rainfall)
log.Printf("光照: %.1f lux", rs485Data.Light)
log.Printf("紫外线: %.1f", rs485Data.UV)
log.Printf("气压: %.2f hPa", rs485Data.Pressure)
log.Printf("接收时间: %s", rs485Data.ReceivedAt.Format("2006-01-02 15:04:05"))
// 注册设备 // 注册设备
protocol := model.NewProtocol(rawData) stationID := fmt.Sprintf("RS485-%s", rs485Data.DeviceID)
idParts, err := protocol.GetCompleteID()
if err == nil {
stationID := fmt.Sprintf("RS485-%s", idParts.Complete.Hex)
model.RegisterDevice(stationID, addr) model.RegisterDevice(stationID, addr)
log.Printf("设备 %s 已注册IP: %s", stationID, addr.String()) log.Printf("设备 %s 已注册IP: %s", stationID, addr.String())
}
// 可选:保存到数据库
// err = model.SaveWeatherData(rs485Data, string(rawData))
// if err != nil {
// log.Printf("保存数据到数据库失败: %v", err)
// } else {
// log.Printf("数据已成功保存到数据库")
// }
} else { } else {
// 尝试解析WIFI数据 // 尝试解析WIFI数据
data, deviceType, err := model.ParseData(rawData) data, deviceType, err := model.ParseData(rawData)
@ -166,14 +209,6 @@ func startUDP() {
} }
} }
} }
// 暂时不保存到数据库
// err = model.SaveWeatherData(data, string(rawData))
// if err != nil {
// log.Printf("保存数据到数据库失败: %v", err)
// } else {
// log.Printf("数据已成功保存到数据库")
// }
} }
} }
@ -258,49 +293,151 @@ func parseHexData(hexStr string) {
return return
} }
// 打印原始数据
log.Println("=== 原始数据分析 ===")
log.Printf("输入的十六进制字符串: %s", hexStr)
log.Printf("解析后的字节数组长度: %d", len(data))
log.Printf("字节数组内容: %v", data)
// 按索引打印每个字节
for i, b := range data {
log.Printf("索引[%2d]: 0x%02X (%d)", i, b, b)
}
// 检查数据有效性 // 检查数据有效性
if !model.ValidateRS485Data(data) { if !model.ValidateRS485Data(data) {
log.Printf("无效的RS485数据格式: 长度=%d, 起始字节=%02X", len(data), data[0]) log.Printf("无效的RS485数据格式: 长度=%d, 起始字节=%02X", len(data), data[0])
return return
} }
log.Println("\n=== 使用Protocol.go标准解析 ===")
// 创建协议解析器 // 创建协议解析器
protocol := model.NewProtocol(data) protocol := model.NewProtocol(data)
rs485Protocol := model.NewRS485Protocol(data) rs485Protocol := model.NewRS485Protocol(data)
// 获取设备ID // 1. 解析设备ID
log.Println("--- 设备ID解析 ---")
idParts, err := protocol.GetCompleteID() idParts, err := protocol.GetCompleteID()
if err != nil { if err != nil {
log.Printf("获取设备ID失败: %v", err) log.Printf("获取设备ID失败: %v", err)
return return
} }
log.Printf("HSB (索引21): 0x%02X = %d", data[21], data[21])
log.Printf("MSB (索引22): 0x%02X = %d", data[22], data[22])
log.Printf("LSB (索引1): 0x%02X = %d", data[1], data[1])
log.Printf("完整设备ID: %s", idParts.Complete.Hex)
// 解析RS485数据 // 2. 解析温度
log.Println("--- 温度解析 ---")
temp, err := protocol.GetTemperature()
if err != nil {
log.Printf("获取温度失败: %v", err)
} else {
log.Printf("TMP_H (bit29-31): %s (0x%X)", temp.TmpH.Binary, temp.TmpH.Value)
log.Printf("TMP_M (bit32-35): %s (0x%X)", temp.TmpM.Binary, temp.TmpM.Value)
log.Printf("TMP_L (bit36-39): %s (0x%X)", temp.TmpL.Binary, temp.TmpL.Value)
log.Printf("原始值: 0x%X = %d", temp.Complete.RawValue, temp.Complete.RawValue)
log.Printf("温度: %.2f°C", temp.Complete.Value)
}
// 3. 解析湿度
log.Println("--- 湿度解析 ---")
humidity, err := protocol.GetHumidity()
if err != nil {
log.Printf("获取湿度失败: %v", err)
} else {
log.Printf("HM_H (bit40-43): %s (0x%X)", humidity.HmH.Binary, humidity.HmH.Value)
log.Printf("HM_L (bit44-47): %s (0x%X)", humidity.HmL.Binary, humidity.HmL.Value)
log.Printf("原始值: 0x%02X = %d", humidity.Complete.RawValue, humidity.Complete.RawValue)
log.Printf("湿度: %d%%", humidity.Complete.Value)
}
// 4. 解析风速
log.Println("--- 风速解析 ---")
windSpeed, err := protocol.GetWindSpeed()
if err != nil {
log.Printf("获取风速失败: %v", err)
} else {
log.Printf("WSP_FLAG: %v", windSpeed.WspFlag.Value)
log.Printf("WSP_H (bit48-51): %s (0x%X)", windSpeed.WspH.Binary, windSpeed.WspH.Value)
log.Printf("WSP_L (bit52-55): %s (0x%X)", windSpeed.WspL.Binary, windSpeed.WspL.Value)
log.Printf("原始值: 0x%X = %d", windSpeed.Complete.RawValue, windSpeed.Complete.RawValue)
log.Printf("风速: %.5f m/s", windSpeed.Complete.Value)
}
// 5. 解析风向
log.Println("--- 风向解析 ---")
windDir, err := protocol.GetWindDirection()
if err != nil {
log.Printf("获取风向失败: %v", err)
} else {
log.Printf("DIR_H: %s (0x%X)", windDir.DirH.Binary, windDir.DirH.Value)
log.Printf("DIR_M: %s (0x%X)", windDir.DirM.Binary, windDir.DirM.Value)
log.Printf("DIR_L: %s (0x%X)", windDir.DirL.Binary, windDir.DirL.Value)
log.Printf("原始值: 0x%X = %d", windDir.Complete.Value, windDir.Complete.Value)
log.Printf("风向: %.1f°", windDir.Complete.Degree)
}
// 6. 解析降雨量
log.Println("--- 降雨量解析 ---")
rainfall, err := protocol.GetRainfall()
if err != nil {
log.Printf("获取降雨量失败: %v", err)
} else {
log.Printf("原始值: 0x%X = %d", rainfall.Complete.RawValue, rainfall.Complete.RawValue)
log.Printf("降雨量: %.3f mm", rainfall.Complete.Value)
}
// 7. 解析光照
log.Println("--- 光照解析 ---")
light, err := protocol.GetLight()
if err != nil {
log.Printf("获取光照失败: %v", err)
} else {
log.Printf("原始值: 0x%X = %d", light.Complete.RawValue, light.Complete.RawValue)
log.Printf("光照: %.1f lux", light.Complete.Value)
}
// 8. 解析UV指数
log.Println("--- UV指数解析 ---")
uv, err := protocol.GetUVIndex()
if err != nil {
log.Printf("获取UV指数失败: %v", err)
} else {
log.Printf("原始值: 0x%X = %d", uv.Complete.RawValue, uv.Complete.RawValue)
log.Printf("UV指数: %.1f uW/c㎡", uv.Complete.Value)
}
// 9. 解析气压
log.Println("--- 气压解析 ---")
pressure, err := protocol.GetPressure()
if err != nil {
log.Printf("获取气压失败: %v", err)
} else {
log.Printf("原始值: 0x%X = %d", pressure.Complete.RawValue, pressure.Complete.RawValue)
log.Printf("气压: %.2f hPa", pressure.Complete.Value)
}
log.Println("\n=== RS485协议统一解析结果 ===")
// 使用修正后的RS485解析
rs485Data, err := rs485Protocol.ParseRS485Data() rs485Data, err := rs485Protocol.ParseRS485Data()
if err != nil { if err != nil {
log.Printf("解析RS485数据失败: %v", err) log.Printf("解析RS485数据失败: %v", err)
return return
} } else {
// 添加设备ID和时间戳
rs485Data.DeviceID = idParts.Complete.Hex rs485Data.DeviceID = idParts.Complete.Hex
rs485Data.ReceivedAt = time.Now() rs485Data.ReceivedAt = time.Now()
rs485Data.RawDataHex = fmt.Sprintf("%X", data) rs485Data.RawDataHex = fmt.Sprintf("%X", data)
// 打印解析结果 log.Printf("设备ID: RS485-%s", rs485Data.DeviceID)
log.Println("=== RS485数据解析结果 ===")
log.Printf("原始数据: %s", hexStr)
log.Printf("设备ID: %s (HSB=%s, MSB=%s, LSB=%s)",
idParts.Complete.Hex,
idParts.HSB.Hex,
idParts.MSB.Hex,
idParts.LSB.Hex)
log.Printf("温度: %.2f°C", rs485Data.Temperature) log.Printf("温度: %.2f°C", rs485Data.Temperature)
log.Printf("湿度: %.1f%%", rs485Data.Humidity) log.Printf("湿度: %.1f%%", rs485Data.Humidity)
log.Printf("风速: %.5f m/s", rs485Data.WindSpeed)
log.Printf("风向: %.1f°", rs485Data.WindDirection) log.Printf("风向: %.1f°", rs485Data.WindDirection)
log.Printf("风速: %.2f m/s", rs485Data.WindSpeed) log.Printf("降雨量: %.3f mm", rs485Data.Rainfall)
log.Printf("降雨量: %.2f mm", rs485Data.Rainfall) log.Printf("光照: %.1f lux", rs485Data.Light)
log.Printf("光照: %.2f lux", rs485Data.Light) log.Printf("紫外线: %.1f", rs485Data.UV)
log.Printf("紫外线: %.2f", rs485Data.UV)
log.Printf("气压: %.2f hPa", rs485Data.Pressure) log.Printf("气压: %.2f hPa", rs485Data.Pressure)
}
} }

View File

@ -774,45 +774,55 @@ type RS485WeatherData struct {
RawDataHex string // 原始数据十六进制 RawDataHex string // 原始数据十六进制
} }
// ParseRS485Data 解析RS485数据 // ParseRS485Data 解析RS485数据 - 使用Protocol标准方法
func (p *RS485Protocol) ParseRS485Data() (*RS485WeatherData, error) { func (p *RS485Protocol) ParseRS485Data() (*RS485WeatherData, error) {
if !ValidateRS485Data(p.RawData) { if !ValidateRS485Data(p.RawData) {
return nil, fmt.Errorf("无效的RS485数据格式") return nil, fmt.Errorf("无效的RS485数据格式")
} }
// 创建标准Protocol来解析数据
protocol := NewProtocol(p.RawData)
data := &RS485WeatherData{} data := &RS485WeatherData{}
// 解析温度 (索引5-6) // 使用Protocol标准方法解析温度
tempRaw := int16(p.RawData[5])<<8 | int16(p.RawData[6]) if temp, err := protocol.GetTemperature(); err == nil {
data.Temperature = float64(tempRaw) / 10.0 data.Temperature = temp.Complete.Value
}
// 解析湿度 (索引7-8) // 使用Protocol标准方法解析湿度
humRaw := int16(p.RawData[7])<<8 | int16(p.RawData[8]) if humidity, err := protocol.GetHumidity(); err == nil {
data.Humidity = float64(humRaw) / 10.0 data.Humidity = float64(humidity.Complete.Value)
}
// 解析风速 (索引9-10) // 使用Protocol标准方法解析风速
windSpeedRaw := int16(p.RawData[9])<<8 | int16(p.RawData[10]) if windSpeed, err := protocol.GetWindSpeed(); err == nil {
data.WindSpeed = float64(windSpeedRaw) / 10.0 data.WindSpeed = windSpeed.Complete.Value
}
// 解析风向 (索引11-12) // 使用Protocol标准方法解析风向
windDirRaw := int16(p.RawData[11])<<8 | int16(p.RawData[12]) if windDir, err := protocol.GetWindDirection(); err == nil {
data.WindDirection = float64(windDirRaw) data.WindDirection = windDir.Complete.Degree
}
// 解析雨量 (索引13-14) // 使用Protocol标准方法解析降雨量
rainRaw := int16(p.RawData[13])<<8 | int16(p.RawData[14]) if rainfall, err := protocol.GetRainfall(); err == nil {
data.Rainfall = float64(rainRaw) / 10.0 data.Rainfall = rainfall.Complete.Value
}
// 解析光照 (索引15-16) // 使用Protocol标准方法解析光照
lightRaw := int16(p.RawData[15])<<8 | int16(p.RawData[16]) if light, err := protocol.GetLight(); err == nil {
data.Light = float64(lightRaw) data.Light = light.Complete.Value
}
// 解析紫外线 (索引17-18) // 使用Protocol标准方法解析UV指数
uvRaw := int16(p.RawData[17])<<8 | int16(p.RawData[18]) if uv, err := protocol.GetUVIndex(); err == nil {
data.UV = float64(uvRaw) / 10.0 data.UV = uv.Complete.Value
}
// 解析气压 (索引19-20) // 使用Protocol标准方法解析气压
pressureRaw := int16(p.RawData[19])<<8 | int16(p.RawData[20]) if pressure, err := protocol.GetPressure(); err == nil {
data.Pressure = float64(pressureRaw) / 10.0 data.Pressure = pressure.Complete.Value
}
return data, nil return data, nil
} }