diff --git a/main.go b/main.go index 1946d10..c037141 100644 --- a/main.go +++ b/main.go @@ -130,18 +130,61 @@ func startUDP() { // 检查数据是否为RS485格式 if len(rawData) == 25 && rawData[0] == 0x24 { + log.Println("=== 检测到RS485设备数据 ===") + + // 生成源码字符串(用于日志记录) + sourceHex := strings.ReplaceAll(strings.TrimSpace(hexDump), "\n", " ") + log.Printf("源码: %s", sourceHex) + // 解析RS485数据 - hexStr := strings.ReplaceAll(hexDump, "\n", " ") - parseHexData(hexStr) + protocol := model.NewProtocol(rawData) + 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) - idParts, err := protocol.GetCompleteID() - if err == nil { - stationID := fmt.Sprintf("RS485-%s", idParts.Complete.Hex) - model.RegisterDevice(stationID, addr) - log.Printf("设备 %s 已注册,IP: %s", stationID, addr.String()) - } + stationID := fmt.Sprintf("RS485-%s", rs485Data.DeviceID) + model.RegisterDevice(stationID, addr) + 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 { // 尝试解析WIFI数据 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 } + // 打印原始数据 + 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) { log.Printf("无效的RS485数据格式: 长度=%d, 起始字节=%02X", len(data), data[0]) return } + log.Println("\n=== 使用Protocol.go标准解析 ===") + // 创建协议解析器 protocol := model.NewProtocol(data) rs485Protocol := model.NewRS485Protocol(data) - // 获取设备ID + // 1. 解析设备ID + log.Println("--- 设备ID解析 ---") idParts, err := protocol.GetCompleteID() if err != nil { log.Printf("获取设备ID失败: %v", err) 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() if err != nil { log.Printf("解析RS485数据失败: %v", err) return + } else { + rs485Data.DeviceID = idParts.Complete.Hex + rs485Data.ReceivedAt = time.Now() + rs485Data.RawDataHex = fmt.Sprintf("%X", data) + + 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) } - - // 添加设备ID和时间戳 - rs485Data.DeviceID = idParts.Complete.Hex - rs485Data.ReceivedAt = time.Now() - rs485Data.RawDataHex = fmt.Sprintf("%X", data) - - // 打印解析结果 - 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("湿度: %.1f%%", rs485Data.Humidity) - log.Printf("风向: %.1f°", rs485Data.WindDirection) - log.Printf("风速: %.2f m/s", rs485Data.WindSpeed) - log.Printf("降雨量: %.2f mm", rs485Data.Rainfall) - log.Printf("光照: %.2f lux", rs485Data.Light) - log.Printf("紫外线: %.2f", rs485Data.UV) - log.Printf("气压: %.2f hPa", rs485Data.Pressure) } diff --git a/model/protocol.go b/model/protocol.go index b45a770..2996962 100644 --- a/model/protocol.go +++ b/model/protocol.go @@ -774,45 +774,55 @@ type RS485WeatherData struct { RawDataHex string // 原始数据十六进制 } -// ParseRS485Data 解析RS485数据 +// ParseRS485Data 解析RS485数据 - 使用Protocol标准方法 func (p *RS485Protocol) ParseRS485Data() (*RS485WeatherData, error) { if !ValidateRS485Data(p.RawData) { return nil, fmt.Errorf("无效的RS485数据格式") } + // 创建标准Protocol来解析数据 + protocol := NewProtocol(p.RawData) data := &RS485WeatherData{} - // 解析温度 (索引5-6) - tempRaw := int16(p.RawData[5])<<8 | int16(p.RawData[6]) - data.Temperature = float64(tempRaw) / 10.0 + // 使用Protocol标准方法解析温度 + if temp, err := protocol.GetTemperature(); err == nil { + data.Temperature = temp.Complete.Value + } - // 解析湿度 (索引7-8) - humRaw := int16(p.RawData[7])<<8 | int16(p.RawData[8]) - data.Humidity = float64(humRaw) / 10.0 + // 使用Protocol标准方法解析湿度 + if humidity, err := protocol.GetHumidity(); err == nil { + data.Humidity = float64(humidity.Complete.Value) + } - // 解析风速 (索引9-10) - windSpeedRaw := int16(p.RawData[9])<<8 | int16(p.RawData[10]) - data.WindSpeed = float64(windSpeedRaw) / 10.0 + // 使用Protocol标准方法解析风速 + if windSpeed, err := protocol.GetWindSpeed(); err == nil { + data.WindSpeed = windSpeed.Complete.Value + } - // 解析风向 (索引11-12) - windDirRaw := int16(p.RawData[11])<<8 | int16(p.RawData[12]) - data.WindDirection = float64(windDirRaw) + // 使用Protocol标准方法解析风向 + if windDir, err := protocol.GetWindDirection(); err == nil { + data.WindDirection = windDir.Complete.Degree + } - // 解析雨量 (索引13-14) - rainRaw := int16(p.RawData[13])<<8 | int16(p.RawData[14]) - data.Rainfall = float64(rainRaw) / 10.0 + // 使用Protocol标准方法解析降雨量 + if rainfall, err := protocol.GetRainfall(); err == nil { + data.Rainfall = rainfall.Complete.Value + } - // 解析光照 (索引15-16) - lightRaw := int16(p.RawData[15])<<8 | int16(p.RawData[16]) - data.Light = float64(lightRaw) + // 使用Protocol标准方法解析光照 + if light, err := protocol.GetLight(); err == nil { + data.Light = light.Complete.Value + } - // 解析紫外线 (索引17-18) - uvRaw := int16(p.RawData[17])<<8 | int16(p.RawData[18]) - data.UV = float64(uvRaw) / 10.0 + // 使用Protocol标准方法解析UV指数 + if uv, err := protocol.GetUVIndex(); err == nil { + data.UV = uv.Complete.Value + } - // 解析气压 (索引19-20) - pressureRaw := int16(p.RawData[19])<<8 | int16(p.RawData[20]) - data.Pressure = float64(pressureRaw) / 10.0 + // 使用Protocol标准方法解析气压 + if pressure, err := protocol.GetPressure(); err == nil { + data.Pressure = pressure.Complete.Value + } return data, nil }