Skip to content

Commit 162dbee

Browse files
committed
Add LoRaWan_Decoders
1 parent 5ddaa5d commit 162dbee

File tree

18 files changed

+2740
-0
lines changed

18 files changed

+2740
-0
lines changed

raw/LoRaWan_Decoders/D20.be

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# LoRaWAN Decoder file for Dragino D20/D22/D23 (1,2,3 temp sensor models)
2+
#
3+
# References
4+
# User Manual: https://wiki.dragino.com/xwiki/bin/view/Main/User%20Manual%20for%20LoRaWAN%20End%20Nodes/D20-LBD22-LBD23-LB_LoRaWAN_Temperature_Sensor_User_Manual/
5+
# TTN Device Repository: https://github.com/TheThingsNetwork/lorawan-devices/blob/master/vendor/dragino/d2x-lb.js
6+
7+
import string
8+
9+
if !global.DrgD20Nodes # data survive to decoder reload
10+
global.DrgD20Nodes = {}
11+
end
12+
13+
class LwDecoDrgD20
14+
def unload()
15+
global.undef("DrgD20Nodes")
16+
global.undef("LwDecoDrgD20")
17+
end
18+
19+
static def decodeUplink(Name, Node, RSSI, FPort, Bytes)
20+
var data = {"Device":"Dragino D20"}
21+
22+
var valid_values = false
23+
var last_seen = 1451602800
24+
var battery_last_seen = 1451602800
25+
var battery = 1000
26+
var rssi = RSSI
27+
var tempC1 = 1000
28+
var tempC2 = 1000
29+
var tempC3 = 1000
30+
31+
if global.DrgD20Nodes.find(Node)
32+
last_seen = global.DrgD20Nodes.item(Node)[2]
33+
battery_last_seen = global.DrgD20Nodes.item(Node)[3]
34+
battery = global.DrgD20Nodes.item(Node)[4]
35+
rssi = global.DrgD20Nodes.item(Node)[5]
36+
tempC1 = global.DrgD20Nodes.item(Node)[6]
37+
tempC2 = global.DrgD20Nodes.item(Node)[7]
38+
tempC3 = global.DrgD20Nodes.item(Node)[8]
39+
end
40+
41+
## SENSOR DATA ##
42+
if 2 == FPort && Bytes.size() == 11
43+
last_seen = tasmota.rtc('local')
44+
var mode=(Bytes[6] & 0x7C)>>2
45+
46+
if 3==mode
47+
battery = (Bytes[0]<<8 | Bytes[1])/1000
48+
data.insert("BattV", battery)
49+
battery_last_seen = tasmota.rtc('local')
50+
51+
# 0x07FF = 2047 = no temp sensor
52+
53+
tempC1 = Bytes[2] << 8 | Bytes[3]
54+
if Bytes[2]>0x7F tempC1-=0x10000 end
55+
tempC1 /= 10.0
56+
data.insert("TempC1", tempC1)
57+
58+
tempC2 = Bytes[7] << 8 | Bytes[8]
59+
if Bytes[7]>0x7F tempC2-=0x10000 end
60+
tempC2 /= 10.0
61+
data.insert("TempC2", tempC2)
62+
63+
tempC3 = Bytes[9] << 8 | Bytes[10]
64+
if Bytes[9]>0x7F tempC3-=0x10000 end
65+
tempC3 /= 10.0
66+
data.insert("TempC3", tempC3)
67+
end
68+
69+
valid_values = true
70+
71+
## STATUS DATA ##
72+
elif 5 == FPort && Bytes.size() == 7
73+
data.insert("Sensor_Model",Bytes[0])
74+
data.insert("Firmware_Version", f'v{Bytes[1]:%u}.{Bytes[2]>>4:%u}.{Bytes[2]&0xF:%u}')
75+
data.insert("Freq_Band",LwRegions[Bytes[3]-1])
76+
data.insert("Sub_Band",Bytes[4])
77+
data.insert("BattV",((Bytes[5] << 8) | Bytes[6]) / 1000.0)
78+
battery_last_seen = tasmota.rtc('local')
79+
battery = ((Bytes[5] << 8) | Bytes[6]) / 1000.0
80+
valid_values = true
81+
else
82+
# Ignore other Fports
83+
end #Fport
84+
85+
if valid_values
86+
if global.DrgD20Nodes.find(Node)
87+
global.DrgD20Nodes.remove(Node)
88+
end
89+
# sensor[0] [1] [2] [3] [4] [5] [6] [7] [8]
90+
global.DrgD20Nodes.insert(Node, [Name, Node, last_seen, battery_last_seen, battery, RSSI, tempC1, tempC2, tempC3])
91+
end
92+
93+
return data
94+
end #decodeUplink()
95+
96+
static def add_web_sensor()
97+
var fmt = global.LwSensorFormatter_cls()
98+
var msg = ""
99+
for sensor: global.DrgD20Nodes
100+
var name = sensor[0]
101+
if string.find(name, "D20") > -1 # If LoRaWanName contains D20 use D20-<node>
102+
name = string.format("D20-%i", sensor[1])
103+
end
104+
var name_tooltip = "Dragino D20"
105+
var last_seen = sensor[2]
106+
var battery_last_seen = sensor[3]
107+
var battery = sensor[4]
108+
var rssi = sensor[5]
109+
msg += fmt.header(name, name_tooltip, battery, battery_last_seen, rssi, last_seen)
110+
111+
# Sensors
112+
var tempC1 = sensor[6]
113+
msg += "<tr class='htr'><td colspan='4'>&#9478;" # |
114+
if tempC1 < 1000
115+
msg += string.format(" &#x2600;&#xFE0F; %.1f°C", tempC1) # Sunshine - Temperature
116+
end
117+
118+
var tempC2 = sensor[7]
119+
if tempC2 < 1000
120+
msg += string.format(" &#x2600;&#xFE0F; %.1f°C", tempC2)
121+
end
122+
123+
var tempC3 = sensor[8]
124+
if tempC3 < 1000
125+
msg += string.format(" &#x2600;&#xFE0F; %.1f°C", tempC3)
126+
end
127+
msg += "{e}" # = </td></tr>
128+
end
129+
return msg
130+
end #add_web_sensor()
131+
end #class
132+
133+
global.LwDeco = LwDecoDrgD20

raw/LoRaWan_Decoders/DDS75L.be

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# LoRaWAN Decoder file for Dragino DDS75-LB/LS
2+
#
3+
# References
4+
# User Manual: https://wiki.dragino.com/xwiki/bin/view/Main/User%20Manual%20for%20LoRaWAN%20End%20Nodes/DDS75-LB_LoRaWAN_Distance_Detection_Sensor_User_Manual/
5+
# TTN Device Repository: https://github.com/TheThingsNetwork/lorawan-devices/blob/master/vendor/dragino/dds75-lb.js
6+
7+
import string
8+
9+
if !global.dds75lbNodes # data survive to decoder reload
10+
global.dds75lbNodes = {}
11+
end
12+
13+
class LwDecoDDS75LB
14+
def unload()
15+
global.undef("dds75lbNodes")
16+
global.undef("LwDecoDDS75LB")
17+
end
18+
19+
static def decodeUplink(Name, Node, RSSI, FPort, Bytes)
20+
var data = {"Device":"Dragino DDS75-LB/LS"}
21+
22+
var valid_values = false
23+
var last_seen = 1451602800
24+
var battery_last_seen = 1451602800
25+
var battery = 1000
26+
var rssi = RSSI
27+
var distance = 0
28+
29+
if global.dds75lbNodes.find(Node)
30+
last_seen = global.dds75lbNodes.item(Node)[2]
31+
battery_last_seen = global.dds75lbNodes.item(Node)[3]
32+
battery = global.dds75lbNodes.item(Node)[4]
33+
rssi = global.dds75lbNodes.item(Node)[5]
34+
distance = global.dds75lbNodes.item(Node)[6]
35+
end
36+
37+
## SENSOR DATA ##
38+
if 2 == FPort && 8 == Bytes.size()
39+
last_seen = tasmota.rtc('local')
40+
41+
battery_last_seen = tasmota.rtc('local')
42+
battery = ((Bytes[0] << 8) | Bytes[1]) / 1000.0
43+
data.insert("BattV",battery)
44+
45+
distance=Bytes[2]<<8 | Bytes[3]
46+
data.insert("Distance",distance)
47+
48+
valid_values = true
49+
50+
## STATUS DATA ##
51+
elif 5 == FPort && 7 == Bytes.size()
52+
data.insert("Sensor_Model",Bytes[0])
53+
data.insert("Firmware_Version", f'v{Bytes[1]:%u}.{Bytes[2]>>4:%u}.{Bytes[2]&0xF:%u}')
54+
data.insert("Freq_Band",LwRegions[Bytes[3]-1])
55+
data.insert("Sub_Band",Bytes[4])
56+
battery_last_seen = tasmota.rtc('local')
57+
battery = ((Bytes[5] << 8) | Bytes[6]) / 1000.0
58+
valid_values = true
59+
else
60+
# Ignore other Fports
61+
end #Fport
62+
63+
if valid_values
64+
if global.dds75lbNodes.find(Node)
65+
global.dds75lbNodes.remove(Node)
66+
end
67+
# sensor[0] [1] [2] [3] [4] [5] [6]
68+
global.dds75lbNodes.insert(Node, [Name, Node, last_seen, battery_last_seen, battery, RSSI, distance])
69+
end
70+
71+
return data
72+
end #decodeUplink()
73+
74+
static def add_web_sensor()
75+
var fmt = global.LwSensorFormatter_cls()
76+
var msg = ""
77+
for sensor: global.dds75lbNodes
78+
var name = sensor[0]
79+
if string.find(name, "DDS75-L") > -1 # If LoRaWanName contains DDS75-L use DDS75-L-<node>
80+
name = string.format("DDS75-L-%i", sensor[1])
81+
end
82+
var name_tooltip = "Dragino DDS75-L"
83+
var last_seen = sensor[2]
84+
var battery_last_seen = sensor[3]
85+
var battery = sensor[4]
86+
var rssi = sensor[5]
87+
msg += fmt.header(name, name_tooltip, battery, battery_last_seen, rssi, last_seen)
88+
89+
# Sensors
90+
var distance = sensor[6]
91+
msg += "<tr class='htr'><td colspan='4'>&#9478;" # |
92+
msg += string.format(" &#11123;&#xFE0F; %.0fmm", distance) # ⭳
93+
msg += "{e}" # = </td></tr>
94+
end
95+
return msg
96+
end #add_web_sensor()
97+
end #class
98+
99+
global.LwDeco = LwDecoDDS75LB

raw/LoRaWan_Decoders/DW10.be

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# LoRaWAN Decoder file for MerryIoT DW10 Open/Close
2+
#
3+
# References
4+
# DW10 Product information: https://www.browan.com/products-detail/OpenClose-Sensor-EBL-LoRaWAN/
5+
# Browan JS Decoder (TTN): https://www.browan.com/member/login/?refererUrl=https%3A%2F%2Fwww.browan.com%2Fproducts-detail%2FOpenClose-Sensor-EBL-LoRaWAN%2F
6+
7+
import string
8+
9+
if !global.dw10Nodes # data survive to decoder reload
10+
global.dw10Nodes = {}
11+
end
12+
13+
class LwDecoDW10
14+
def unload()
15+
global.undef("dw10Nodes")
16+
global.undef("LwDecoDW10")
17+
end
18+
19+
static def decodeUplink(Name, Node, RSSI, FPort, Bytes)
20+
var data = {"Device":"MerryIoT DW10"}
21+
22+
var valid_values = false
23+
var last_seen = 1451602800
24+
var battery_last_seen = 1451602800
25+
var battery
26+
var rssi = RSSI
27+
var door_open
28+
var door_open_last_seen = 1451602800
29+
var button_pressed
30+
var temperature
31+
var humidity
32+
if global.dw10Nodes.find(Node)
33+
door_open = global.dw10Nodes.item(Node)[6]
34+
door_open_last_seen = global.dw10Nodes.item(Node)[7]
35+
end
36+
## SENSOR DATA ##
37+
if 120 == FPort && Bytes.size() == 9
38+
last_seen = tasmota.rtc('local')
39+
40+
var last_door_open = door_open
41+
door_open = ( Bytes[0] & 0x01 ) ? 1 : 0
42+
data.insert("DoorOpen", ( door_open ) ? true : false )
43+
if last_door_open != door_open
44+
door_open_last_seen = tasmota.rtc('local')
45+
end
46+
47+
button_pressed = ( Bytes[0] & 0x02 ) ? 1 : 0
48+
data.insert("ButtonPress", ( button_pressed ) ? true : false )
49+
data.insert("TamperDetect", ( Bytes[0] & 0x04 ) ? true : false )
50+
data.insert("TiltDetect", ( Bytes[0] & 0x08 ) ? true : false )
51+
data.insert("BattV", (( 21 + Bytes[1] ) * 100) / 1000.0 )
52+
battery_last_seen = tasmota.rtc('local')
53+
battery = (( 21 + Bytes[1] ) * 100) / 1000.0
54+
data.insert("TemperatureC", Bytes[2])
55+
temperature = Bytes[2]
56+
data.insert("Humidity", Bytes[3])
57+
humidity = Bytes[3]
58+
data.insert("DoorOpenLastDuration_mins", Bytes[4] | (Bytes[5] << 8))
59+
data.insert("DoorOpenEvents", Bytes[6] | (Bytes[7] << 8) | (Bytes[8] << 16 ))
60+
valid_values = true
61+
else
62+
# Ignore other Fports
63+
end #Fport
64+
65+
if valid_values
66+
if global.dw10Nodes.find(Node)
67+
global.dw10Nodes.remove(Node)
68+
end
69+
# sensor[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
70+
global.dw10Nodes.insert(Node, [Name, Node, last_seen, battery_last_seen, battery, RSSI, door_open, door_open_last_seen, button_pressed, temperature, humidity])
71+
end
72+
73+
return data
74+
end #decodeUplink()
75+
76+
static def add_web_sensor()
77+
var fmt = global.LwSensorFormatter_cls()
78+
var msg = ""
79+
for sensor: global.dw10Nodes
80+
var name = sensor[0]
81+
if string.find(name, "DW10") > -1 # If LoRaWaName contains DW10 use DW10-<node>
82+
name = string.format("DW10-%i", sensor[1])
83+
end
84+
var name_tooltip = "MerryIoT DW10"
85+
var last_seen = sensor[2]
86+
var battery_last_seen = sensor[3]
87+
var battery = sensor[4]
88+
var rssi = sensor[5]
89+
msg += fmt.header(name, name_tooltip, battery, battery_last_seen, rssi, last_seen)
90+
91+
# Sensors
92+
var door_open = sensor[6]
93+
var door_open_last_seen = sensor[7]
94+
var button_pressed = sensor[8]
95+
var temperature = sensor[9]
96+
var humidity = sensor[10]
97+
msg += "<tr class='htr'><td colspan='4'>&#9478;" # |
98+
msg += string.format(" &#x2600;&#xFE0F; %.1f°C", temperature) # Sunshine - Temperature
99+
msg += string.format(" &#x1F4A7; %.1f%%", humidity) # Raindrop - Humidity
100+
msg += string.format(" %s %s", (door_open) ? "&#x1F513" : "&#x1F512", # Open or Closed lock - Door
101+
fmt.dhm(door_open_last_seen))
102+
msg += "{e}" # = </td></tr>
103+
end
104+
return msg
105+
end #add_web_sensor()
106+
end #class
107+
108+
global.LwDeco = LwDecoDW10

0 commit comments

Comments
 (0)