Hi,
as there is no port of the Davis binding to OpenHAB 3, i made an alternative solution using the serial binding and rules. It is so far able to extract data from the two main messages sent by Davis Vantgae Pro2, but it should not be to hard to extend or adapt to other versions of Davis weatherstations. This solution uses the text file configuration approach, see below.
Have fun!
davis.things
Bridge serial:serialBridge:davis [serialPort = "/dev/ttyUSB.davis", baudRate = 19200, charset = "ISO-8859-1"]
davis.items
Group gDavis
String Davis_rawString {channel="serial:serialBridge:davis:string"}
String Davis_rawBinary {channel="serial:serialBridge:davis:binary"}
String Davis_rawDataTrigger {channel="serial:serialBridge:davis:data"}
//LOOP msg
Number Davis_Barometer "Barometer [%.0f hPa]" <pressure> (gDavis)
Number Davis_InsideTemp "Dachboden Wetterstation [%.1f °C]" <temperature> (gDavis)
Number Davis_InsideHum "Dachboden Wetterstation [%.0f %% ]" <humidity> (gDavis)
Number Davis_OutsideTemp "Outside Temp [%.1f °C]" <temperature> (gDavis,TemperatureOutside)
Number Davis_WindSpeed "Wind Speed [%.1f km/h]" <wind> (gDavis)
Number Davis_WindSpeed10minAvg "Wind Speed 10min Avg [%.1f km/h]" <wind> (gDavis)
Number Davis_WindDirection "Wind Richtung [%.0f °]" <wind> (gDavis)
Number Davis_OutsideHum "Outside Hum [%.0f %% ]" <humidity> (gDavis)
Number Davis_RainRate "Rain Rate [%.1f mm/h ]" <rain> (gDavis)
Number Davis_UVIndex "UV Index [%.1f ]" <sun> (gDavis)
Number Davis_Solar "Solar Radiation [%.0f W/m²]" <sun> (gDavis)
Number Davis_TransmitterBattery "Transmitter Battery [%.1f]" <energy> (gDavis)
Number Davis_ConsoleBatteryVoltage "Console Battery [%.2f V]" <energy> (gDavis)
//LOOP2 msg
//some are already included in LOOP
Number Davis_WindSpeed10minHiRes "Wind Speed 10min Avg HiRes [%.2f km/h]" <wind> (gDavis)
Number Davis_WindSpeed2minHiRes "Wind Speed 2min Avg HiRes [%.2f km/h]" <wind> (gDavis)
Number Davis_WindSpeed10minGustHiRes "Wind Speed 10min BöeHiRes [%.2f km/h]" <wind> (gDavis)
Number Davis_WindDirectionGust "Wind Richtung Böen [%.0f °]" <wind> (gDavis)
Number Davis_DewPoint "Dew Point [%.1f °C]" <temperature> (gDavis)
Number Davis_Rain15min "Rain Rate 15min [%.1f mm/h ]" <rain> (gDavis)
Number Davis_Rainlast1h "Rain Rate 1h [%.1f mm/h ]" <rain> (gDavis)
Number Davis_Rainlast24h "Rain Rate 24h [%.1f mm/h ]" <rain> (gDavis)
davis.rules
import java.nio.ByteBuffer
import java.nio.ByteOrder
var String packetFormat = ""
var String responseType
var String responseLimiterType
var int responseLen
var String crcType
var int loopType = 1
val publishValue = [
NumberItem trgtItem,Number newVal,Number minVal,Number maxVal |
if (newVal >= minVal && newVal <= maxVal) {
trgtItem.postUpdate(newVal)
}
true
]
rule "Send Davis Cmd"
when
Time cron "5/10 * * * * ? *"
then
if (packetFormat == "") {
sendCommand(Davis_rawString,"LPS "+loopType+" 1\n")
packetFormat = "LOOP"
responseType = "ACK"
responseLimiterType = "FIXED_SIZE"
responseLen = 99
crcType = "VAR1"
if (loopType==2) {
loopType = 1
} else {
loopType = 2
}
} else {
logWarn("Davis", "skipping sending LOOP2 command due to late response")
packetFormat = ""
}
end
rule "Davis bin data received"
when
Item Davis_rawBinary received update
then
//logInfo("Davis", "binary data received!! " + Davis_rawBinary)
var byte[] byteArray = RawType.valueOf(Davis_rawBinary.state.toString()).getBytes()
var ByteBuffer data = ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN)
var offset = 0
if (packetFormat == "") {
logWarn("Davis", "recevied without prior sending command")
return;
}
switch responseType {
case "ACK": {
offset = 1
}
case "OK": {
offset = 6
}
}
switch responseLimiterType {
case "FIXED_SIZE": {
if (byteArray.length - offset == responseLen) {
//logInfo("Davis", "response length as expected")
} else {
logWarn("Davis", "wrong response length: "+byteArray.length)
packetFormat = ""
}
}
case "CRLF": {
if (data.get(byteArray.length-2) == '\n' && data.get(byteArray.length-1) == '\r') {
//logInfo("Davis", "response end as expected")
} else {
logWarn("Davis", "wrong response end (no CRLF), length: "+byteArray.length)
packetFormat = ""
}
}
}
/*
if (crcType == "VAR1") {
//TODO migrate CRC16 to rule using lamba expressions, check if possible
if (CRC16.check(responseBlock, offset, responseBlock.length - offset)) {
//CRC ok
} else {
//CRC faulty
}
}
*/
if (packetFormat=="LOOP") {
if ((data.get(offset+0) == 0x4C) && (data.get(offset+1) == 0x4F) && (data.get(offset+2) == 0x4F)) {
if (data.get(offset+4) == 0x00) {
publishValue.apply(Davis_Barometer,(data.getShort(offset+7) * 0.0338638),700,1300)
publishValue.apply(Davis_InsideTemp,((data.getShort(offset+9) * 0.1 - 32) * 5 / 9.0),0,40)
publishValue.apply(Davis_InsideHum,(data.get(offset+11) * 1.0),0,100)
publishValue.apply(Davis_OutsideTemp,((data.getShort(offset+12) * 0.1 - 32) * 5 / 9.0),-40,85)
publishValue.apply(Davis_WindSpeed,(data.get(offset+14) * 1.609344),0,200)
publishValue.apply(Davis_WindSpeed10minAvg,(data.get(offset+15) * 1.609344),0,200)
publishValue.apply(Davis_WindDirection,(data.getShort(offset+16) * 0.1),0,360)
publishValue.apply(Davis_OutsideHum,(data.get(offset+33) * 1.0),0,100)
publishValue.apply(Davis_RainRate,(data.getShort(offset+41) * 0.2),0,1000)
publishValue.apply(Davis_UVIndex,(data.get(offset+43) * 0.1),0,10)
publishValue.apply(Davis_Solar,(data.getShort(offset+44) * 1.0),0,1500)
publishValue.apply(Davis_TransmitterBattery,(data.get(offset+86) * 1.0),0,1)
publishValue.apply(Davis_ConsoleBatteryVoltage,(data.getShort(offset+87) * 0.00585937),0,10)
logInfo("Davis", "LOOP decoded!!")
} else if (data.get(offset+4) == 0x01) {
publishValue.apply(Davis_Barometer,(data.getShort(offset+7) * 0.0338638),700,1300)
publishValue.apply(Davis_InsideTemp,((data.getShort(offset+9) * 0.1 - 32) * 5 / 9.0),0,40)
publishValue.apply(Davis_InsideHum,(data.get(offset+11) * 1.0),0,100)
publishValue.apply(Davis_OutsideTemp,((data.getShort(offset+12) * 0.1 - 32) * 5 / 9.0),-40,85)
publishValue.apply(Davis_WindSpeed,(data.get(offset+14) * 1.609344),0,200)
publishValue.apply(Davis_WindDirection,(data.getShort(offset+16) * 0.1),0,360)
publishValue.apply(Davis_WindSpeed10minHiRes,(data.getShort(offset+18) * 0.1609344),0,200)
publishValue.apply(Davis_WindSpeed2minHiRes,(data.getShort(offset+20) * 0.1609344),0,200)
publishValue.apply(Davis_WindSpeed10minGustHiRes,(data.getShort(offset+22) * 0.1609344),0,200)
publishValue.apply(Davis_WindDirectionGust,(data.getShort(offset+24) * 0.1),0,360)
publishValue.apply(Davis_DewPoint,((data.getShort(offset+30) - 32) * 5 / 9.0),-40,85)
publishValue.apply(Davis_OutsideHum,(data.get(offset+33) * 1.0),0,100)
publishValue.apply(Davis_RainRate,(data.getShort(offset+41) * 0.2),0,1000)
publishValue.apply(Davis_Rain15min,(data.getShort(offset+52) * 0.2),0,1000)
publishValue.apply(Davis_Rainlast1h,(data.getShort(offset+54) * 0.2),0,1000)
publishValue.apply(Davis_Rainlast24h,(data.getShort(offset+58) * 0.2),0,1000)
logInfo("Davis", "LOOP2 decoded!!")
} else {
logWarn("Davis", "Invalid LOOP packet("+Integer::toHexString(data.get(offset+4))+")!")
}
} else {
logWarn("Davis", "Unexpected packet(0x"+Integer::toHexString(data.get(offset+0))+" 0x"+Integer::toHexString(data.get(offset+1))+" 0x"+Integer::toHexString(data.get(offset+2))+"), LOOP expected!")
}
} else {
logWarn("Davis", "Unexpected packet!")
}
packetFormat = ""
end