Monday, November 28, 2016

More sensors for Tellstick local access

After obtaining local network access to the Tellstick net I also have a wind sensor and a rain sensor close to my Tellstick net. Again, translating the Telldus .cpp code to python, the following python code gives the same results as the Telldus Live page. The code for the 1984/1994 sensors are identical except for the:
checksum = checksum + 0x1 + 0x9 + 0x8 + 0x4
vs
checksum = checksum + 0x1 + 0x9 + 0x9 + 0x4
checksum calculation. Here are the python code.
def decode2914(inp):
#source:telldus-core/service/ProtocolOregon.cpp@c9567f
#// rain
value = int(inp, 16)
messageChecksum1 = value & 0xF
value  = value >> 4
messageChecksum2 = value & 0xF
value  = value >> 4
totRain1 = value & 0xF
value  = value >> 4
totRain2 = value & 0xF
value  = value >> 4
totRain3 = value & 0xF
value  = value >> 4
totRain4 = value & 0xF
value  = value >> 4
totRain5 = value & 0xF
value  = value >> 4
totRain6 = value & 0xF
value  = value >> 4
rainRate1 = value & 0xF
value  = value >> 4
rainRate2 = value & 0xF
value  = value >> 4
rainRate3 = value & 0xF
value  = value >> 4
rainRate4 = value & 0xF
value  = value >> 4
battery = value & 0xF #// PROBABLY battery
value  = value >> 4
rollingcode = ((value >> 4) & 0xF) + (value & 0xF)
checksum =    ((value >> 4) & 0xF) + (value & 0xF)
value  = value >> 8
channel = value & 0xF
checksum = checksum + totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 +\
rainRate1 + rainRate2 + rainRate3 + rainRate4 +\
battery + channel + 0x2 + 0x9 + 0x1 + 0x4
if (((checksum >> 4) & 0xF) != messageChecksum1 or (checksum & 0xF) != messageChecksum2):
#// checksum error
return ""
totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) +\
(totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4
rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4

return "%f\t%f"%(totRain, rainRate)



def decode1994(inp):
#source:telldus-core/service/ProtocolOregon.cpp@c9567f
#wind
value = int(inp, 16)
crcCheck = value & 0xF
value  = value >> 4
messageChecksum1 = value & 0xF
value  = value >> 4
messageChecksum2 = value & 0xF
value  = value >> 4
avg1 = value & 0xF
value  = value >> 4
avg2 = value & 0xF
value  = value >> 4
avg3 = value & 0xF
value  = value >> 4
gust1 = value & 0xF
value  = value >> 4
gust2 = value & 0xF
value  = value >> 4
gust3 = value & 0xF
value  = value >> 4
unknown1 = value & 0xF
value  = value >> 4
unknown2 = value & 0xF
value  = value >> 4
direction = value & 0xF
value  = value >> 4
battery = value & 0xF  #// PROBABLY battery
value  = value >> 4
rollingcode = ((value >> 4) & 0xF) + (value & 0xF)
checksum =    ((value >> 4) & 0xF) + (value & 0xF)
value  = value >> 8
channel = value & 0xF
checksum = checksum + unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel
checksum = checksum + 0x1 + 0x9 + 0x9 + 0x4
if (((checksum >> 4) & 0xF) != messageChecksum1 or (checksum & 0xF) != messageChecksum2):
#// checksum error
return ""
avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0
gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0
directiondegree = 22.5 * direction
return '%f\t%f\t%f'%(avg, gust, directiondegree)

def decode1984(inp):
#source:telldus-core/service/ProtocolOregon.cpp@c9567f
#// wind
value = int(inp, 16)
crcCheck = value & 0xF
value  = value >> 4
messageChecksum1 = value & 0xF
value  = value >> 4
messageChecksum2 = value & 0xF
value  = value >> 4
avg1 = value & 0xF
value  = value >> 4
avg2 = value & 0xF
value  = value >> 4
avg3 = value & 0xF
value  = value >> 4
gust1 = value & 0xF
value  = value >> 4
gust2 = value & 0xF
value  = value >> 4
gust3 = value & 0xF
value  = value >> 4
unknown1 = value & 0xF
value  = value >> 4
unknown2 = value & 0xF
value  = value >> 4
direction = value & 0xF
value  = value >> 4
battery = value & 0xF  #// PROBABLY battery
value  = value >> 4
rollingcode = ((value >> 4) & 0xF) + (value & 0xF)
checksum =    ((value >> 4) & 0xF) + (value & 0xF)
value  = value >> 8
channel = value & 0xF
checksum = checksum + unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel
checksum = checksum + 0x1 + 0x9 + 0x8 + 0x4
if (((checksum >> 4) & 0xF) != messageChecksum1 or (checksum & 0xF) != messageChecksum2):
#// checksum error
return ""
avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0
gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0
directiondegree = 22.5 * direction

return '%f\t%f\t%f'%(avg, gust, directiondegree)
Just add some more checks in the while loop
while 1:
try:
data,(address, port) = sock.recvfrom(1040)
#print data
if (data.split(":")[6][6:10]=="F824"):
#print data.split(":")[7][5:5+14]
print decodeF824(data.split(":")[7][5:5+14])
elif (data.split(":")[6][6:10]=="1984"):
#print data.split(":")[7][5:5+16]
print decode1984(data.split(":")[7][5:5+16])
elif (data.split(":")[6][6:10]=="2914"):
#print data.split(":")[7][5:5+16]
print decode2914(data.split(":")[7][5:5+16])
else:
print data
#fp.write(data + '\n');
#fp.flush()
except KeyboardInterrupt:
print "done"
#fp.close()
break
except: # time out, try again
pass


2 comments:

  1. Ok, so I'm trying to achieve something similar on for my Tellstick zNet Lite v2. How ever, what I've got is not working yet.

    So far I read what protocol is used and extract the datai value and convert that into binary. From what I've understand one may extract significant bits from the binary value and read them as the important values. Might be a difficult path though. :/

    ReplyDelete
  2. Hi. If you have the binary data you should be able to decode it via a script alla "decode1984" or similar suitable for your device. I would be suprised it the Telldus changed the format of the radio transmission.

    Have you checked for your device in "https://github.com/telldus/telldus/tree/master/telldus-core/service"?

    ReplyDelete