feat: add a new 485 type weather station

This commit is contained in:
yarnom 2025-08-01 21:37:46 +08:00
parent 67fe281c0a
commit 686cf8847e

View File

@ -243,75 +243,78 @@ func ParseWH65LPData(data []byte) (*WH65LPData, error) {
Timestamp: time.Now(), Timestamp: time.Now(),
} }
// 1. 解析家族码 (第1字节bits 0-7) // 1. 家族码 (第1字节bits 0-7)
wd.FamilyCode = data[0] wd.FamilyCode = data[0]
if wd.FamilyCode != 0x24 { if wd.FamilyCode != 0x24 {
return nil, fmt.Errorf("无效的家族码0x%02X", wd.FamilyCode) return nil, fmt.Errorf("无效的家族码0x%02X", wd.FamilyCode)
} }
// 2. 解析设备ID (第2字节 + 第22-23字节) // 2. 设备ID (第2字节 + 第22-23字节)
idLSB := data[1] idLSB := uint32(data[1]) // bits 8-15
idMSB := uint32(data[22]) | uint32(data[21])<<8 idMSB := uint32(data[22]) | uint32(data[21])<<8 // bits 168-183
wd.StationID = fmt.Sprintf("%06X", (idMSB<<8)|uint32(idLSB)) wd.StationID = fmt.Sprintf("%06X", (idMSB<<8)|idLSB)
// 3. 解析风向 (bits 16-24) // 3. 风向 (bits 16-24)
// 第3字节完整8位 + 第4字节的最低位 // 取第3字节的8位 + 第4字节的第1位
windDir := uint16(data[2]) | ((uint16(data[3]) & 0x01) << 8) windDirLow := uint16(data[2]) // bits 16-23
windDirHigh := uint16(data[3] & 0x01) // bit 24
windDir := windDirLow | (windDirHigh << 8)
wd.WindDirection = int(windDir) % 360 wd.WindDirection = int(windDir) % 360
// 4. 风速标志和温度 // 4. WSP_FLAG (bit 25)
// WSP_FLAG 在第4字节的第2位 (bit 25)
wd.WSPFlag = (data[3]>>1)&0x01 == 1 wd.WSPFlag = (data[3]>>1)&0x01 == 1
// 低电量标志在第4字节的第4位 (bit 28)
wd.LowBattery = (data[3]>>3)&0x01 == 1
// 5. 温度 (bits 28-39) // 5. WSP_9 和 WSP_8 (bits 26-27)
// 从第4字节的高4位和第5字节的低3位组合出11位温度数据 wspHigh := uint16((data[3] >> 2) & 0x03)
tempRaw := ((uint16(data[3]) >> 4) & 0x07) | (uint16(data[4]) << 3)
// 6. 低电量标志 (bit 28)
wd.LowBattery = (data[3]>>4)&0x01 == 1
// 7. 温度 (bits 29-39) - 11位数据
// 从第4字节的高3位 + 第5字节的完整8位
tempLow := uint16(data[4]) // bits 29-36 (实际是32-39)
tempHigh := uint16((data[3] >> 5) & 0x07) // bits 29-31
tempRaw := tempLow | (tempHigh << 8)
wd.Temperature = float64(tempRaw-400) / 10.0 wd.Temperature = float64(tempRaw-400) / 10.0
// 6. 湿度 (bits 40-47) // 8. 湿度 (bits 40-47)
// 第5字节的高5位 wd.Humidity = int(data[5])
wd.Humidity = int(data[4] >> 3)
// 7. 风速 (bits 48-55 + WSP_9,WSP_8) // 9. 风速 (bits 48-55 + WSP_9,WSP_8)
windSpeedRaw := uint16(data[6]) windSpeedLow := uint16(data[6]) // bits 48-55
if !wd.WSPFlag { if wd.WSPFlag {
// 10位风速从第4字节的bits 6-7获取高2位 // 9位风速
windSpeedRaw |= uint16((data[3]>>6)&0x03) << 8 wd.WindSpeed = float64(windSpeedLow) / 8.0 * 0.51
} } else {
// 10位风速加上bits 26-27的WSP_9和WSP_8
windSpeedRaw := windSpeedLow | (wspHigh << 8)
wd.WindSpeed = float64(windSpeedRaw) / 8.0 * 0.51 wd.WindSpeed = float64(windSpeedRaw) / 8.0 * 0.51
}
// 8. 阵风 (bits 56-63) // 10. 阵风 (bits 56-63)
wd.WindGust = float64(data[7]) * 0.51 wd.WindGust = float64(data[7]) * 0.51
// 9. 降雨量 (bits 64-79) // 11. 降雨量 (bits 64-79)
rainRaw := uint16(data[8]) | uint16(data[9])<<8 rainRaw := uint16(data[8]) | uint16(data[9])<<8
wd.Rain = float64(rainRaw) * 0.254 wd.Rain = float64(rainRaw) * 0.254
// 10. 紫外线 (bits 80-95) // 12. 紫外线 (bits 80-95)
uvRaw := uint16(data[10]) | uint16(data[11])<<8 uvRaw := uint16(data[10]) | uint16(data[11])<<8
wd.UV = getUVIndex(uvRaw) wd.UV = getUVIndex(uvRaw)
// 11. 光照 (bits 96-119) // 13. 光照 (bits 96-119)
lightRaw := uint32(data[12]) | uint32(data[13])<<8 | uint32(data[14])<<16 lightRaw := uint32(data[12]) | uint32(data[13])<<8 | uint32(data[14])<<16
wd.Light = float64(lightRaw) / 10.0 wd.Light = float64(lightRaw) / 10.0
// 12. 气压 (bits 136-159) // 14. 气压 (bits 136-159) - 从第18-20字节 (索引17-19)
// 从第18-20字节提取17位气压数据
pressureRaw := uint32(data[17]) | uint32(data[18])<<8 | uint32(data[19])<<16 pressureRaw := uint32(data[17]) | uint32(data[18])<<8 | uint32(data[19])<<16
pressureRaw &= 0x1FFFF pressureRaw &= 0x1FFFF // 只取17位
if pressureRaw == 0x1FFFF { if pressureRaw == 0x1FFFF {
wd.Pressure = 0 // 无效值 wd.Pressure = 0 // 无效值
} else { } else {
wd.Pressure = float64(pressureRaw) / 100.0 wd.Pressure = float64(pressureRaw) / 100.0
} }
// 13. 验证校验和
if !IsWH65LPData(data) {
return nil, fmt.Errorf("数据校验失败")
}
return wd, nil return wd, nil
} }