From 67fe281c0ab876fb6924d4d587c3a298c4af0a98 Mon Sep 17 00:00:00 2001 From: yarnom Date: Fri, 1 Aug 2025 21:34:35 +0800 Subject: [PATCH] feat: add a new 485 type weather station --- model/weather_data.go | 67 ++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/model/weather_data.go b/model/weather_data.go index 0590b24..0c6e10a 100644 --- a/model/weather_data.go +++ b/model/weather_data.go @@ -255,49 +255,59 @@ func ParseWH65LPData(data []byte) (*WH65LPData, error) { wd.StationID = fmt.Sprintf("%06X", (idMSB<<8)|uint32(idLSB)) // 3. 解析风向 (bits 16-24) - windDir := uint16(data[2]) | (uint16(data[3]&0x01) << 8) - wd.WindDirection = int(windDir) + // 第3字节完整8位 + 第4字节的最低位 + windDir := uint16(data[2]) | ((uint16(data[3]) & 0x01) << 8) + wd.WindDirection = int(windDir) % 360 - // 4. 解析风速标志和温度 + // 4. 风速标志和温度 + // WSP_FLAG 在第4字节的第2位 (bit 25) wd.WSPFlag = (data[3]>>1)&0x01 == 1 + // 低电量标志在第4字节的第4位 (bit 28) wd.LowBattery = (data[3]>>3)&0x01 == 1 - // 温度 (11位,bits 28-39) - tempRaw := uint16(data[4]) | (uint16(data[5]&0x07) << 8) + // 5. 温度 (bits 28-39) + // 从第4字节的高4位和第5字节的低3位组合出11位温度数据 + tempRaw := ((uint16(data[3]) >> 4) & 0x07) | (uint16(data[4]) << 3) wd.Temperature = float64(tempRaw-400) / 10.0 - // 5. 湿度 (bits 40-47) - wd.Humidity = int(data[5] >> 3) + // 6. 湿度 (bits 40-47) + // 第5字节的高5位 + wd.Humidity = int(data[4] >> 3) - // 6. 风速 (bits 48-55 + WSP_9,WSP_8) + // 7. 风速 (bits 48-55 + WSP_9,WSP_8) windSpeedRaw := uint16(data[6]) if !wd.WSPFlag { - // 10位风速 + // 10位风速,从第4字节的bits 6-7获取高2位 windSpeedRaw |= uint16((data[3]>>6)&0x03) << 8 } wd.WindSpeed = float64(windSpeedRaw) / 8.0 * 0.51 - // 7. 阵风 (bits 56-63) + // 8. 阵风 (bits 56-63) wd.WindGust = float64(data[7]) * 0.51 - // 8. 降雨量 (bits 64-79) + // 9. 降雨量 (bits 64-79) rainRaw := uint16(data[8]) | uint16(data[9])<<8 wd.Rain = float64(rainRaw) * 0.254 - // 9. 紫外线 (bits 80-95) + // 10. 紫外线 (bits 80-95) uvRaw := uint16(data[10]) | uint16(data[11])<<8 wd.UV = getUVIndex(uvRaw) - // 10. 光照 (bits 96-119) + // 11. 光照 (bits 96-119) lightRaw := uint32(data[12]) | uint32(data[13])<<8 | uint32(data[14])<<16 wd.Light = float64(lightRaw) / 10.0 - // 11. 气压 (bits 136-159) + // 12. 气压 (bits 136-159) + // 从第18-20字节提取17位气压数据 pressureRaw := uint32(data[17]) | uint32(data[18])<<8 | uint32(data[19])<<16 - pressureRaw &= 0x1FFFF // 只取17位 - wd.Pressure = float64(pressureRaw) / 100.0 + pressureRaw &= 0x1FFFF + if pressureRaw == 0x1FFFF { + wd.Pressure = 0 // 无效值 + } else { + wd.Pressure = float64(pressureRaw) / 100.0 + } - // 验证校验和 + // 13. 验证校验和 if !IsWH65LPData(data) { return nil, fmt.Errorf("数据校验失败") } @@ -305,6 +315,29 @@ func ParseWH65LPData(data []byte) (*WH65LPData, error) { return wd, nil } +// 调试辅助函数 +func getBits(data []byte, startBit, length int) uint32 { + var result uint32 + startByte := startBit / 8 + startBitInByte := startBit % 8 + + // 从起始字节开始读取 + result = uint32(data[startByte]) >> startBitInByte + bitsGot := 8 - startBitInByte + + // 如果需要更多位,继续读取后续字节 + for bitsGot < length { + startByte++ + result |= uint32(data[startByte]) << bitsGot + bitsGot += 8 + } + + // 只保留需要的位数 + result &= (1 << length) - 1 + + return result +} + // getUVIndex 根据UV原始值获取UV指数 func getUVIndex(uvRaw uint16) int { switch {