-
Notifications
You must be signed in to change notification settings - Fork 20
/
readLoRa.py
339 lines (263 loc) · 15.6 KB
/
readLoRa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#!/usb/bin/env python
import sys
import os
import time
import array
import state
import struct
import util
import crcpython2
import traceback
import updateBlynk
try:
import conflocal as config
except ImportError:
import config
WXLINKPROTOCOLID = 3
# change this if you have changed the SolarMAX protocol number 8 is for SolarMAX Lipo and 10 is for SolarMAX LeadAcid
if(config.SolarMAX_Type == "LEAD"):
SOLARMAXPROTOCOL = 10
else:
SOLARMAXPROTOCOL = 8
# read WXLink and return list to set variables
crcCalc = crcpython2.CRCCCITT(version='XModem')
def readWXLink(block1, block2, stringblock1, stringblock2, block1_orig, block2_orig):
if (config.SWDEBUG):
print "Starting readWXLink"
#oldblock1 = block1
#oldblock2 = block2
try:
if ((len(block1) > 0) and (len(block2) > 0)):
# check crc for errors - don't update data if crc is bad
if (config.SWDEBUG):
print ("block1 length=", len(block1))
print ("block2 length=", len(block2))
#get crc from data
receivedCRC = struct.unpack('H', str(block2[29:31]))[0]
#swap bytes for receivedCRC
receivedCRC = (((receivedCRC)>>8) | ((receivedCRC&0xFF)<<8))&0xFFFF
if (config.SWDEBUG):
print "ReversedreceivedCRC= %x" % receivedCRC
print "length of stb1+sb2=", len(stringblock1+stringblock2)
print ''.join('{:02x}'.format(ord(x)) for x in stringblock1)
print ''.join('{:02x}'.format(ord(x)) for x in stringblock2)
calculatedCRC = crcCalc.calculate(block1+block2[0:27])
if (config.SWDEBUG):
print "calculatedCRC = %x " % calculatedCRC
# check for start bytes, if not present, then invalidate CRC
if (block1[0] != 0xAB) or (block1[1] != 0x66):
calculatedCRC = receivedCRC + 1
if (receivedCRC == calculatedCRC):
if (config.SWDEBUG):
print "Good CRC Recived"
# read protocol
protocol_byte = block1[2]
#protocol_byte = struct.unpack('B', str(block1[2:2]))[0]
protocol_ID = protocol_byte / 10
protocol_software_version = protocol_byte - protocol_ID*10
if (config.SWDEBUG):
print("protocol_ID = ", protocol_ID)
print("protocol_software_version = ", protocol_software_version)
# if protocol_ID == 3, then
# use if: SolarMAX_Present == False or Dual_MAX_WXLink == True
if ((protocol_ID == WXLINKPROTOCOLID) and ((config.SolarMAX_Present == False) or (config.Dual_MAX_WXLink == True))): # 3 is the WXLink Protocol
print("protocol %d - WXLink received "% WXLINKPROTOCOLID)
currentWindSpeed = struct.unpack('f', str(block1[9:13]))[0]
currentWindGust = 0.0 # not implemented in Solar WXLink version
totalRain = struct.unpack('l', str(block1[17:21]))[0]
if (config.SWDEBUG):
print("Rain Total=\t%0.2f in")%(totalRain/25.4)
print("Wind Speed=\t%0.2f MPH")%(currentWindSpeed/1.6)
currentWindDirection = struct.unpack('H', str(block1[7:9]))[0]
if (config.SWDEBUG):
print "Wind Direction=\t\t\t %i Degrees" % currentWindDirection
# now do the AM2315 Temperature
temperature = struct.unpack('f', str(block1[25:29]))[0]
if (config.SWDEBUG):
print "OTFloat=%x%x%x%x" %(block1[25], block1[26], block1[27], block1[28])
elements = [block1[29], block1[30], block1[31], block2[0]]
outHByte = bytearray(elements)
humidity = struct.unpack('f', str(outHByte))[0]
if (config.SWDEBUG):
print "AM2315 from WXLink temperature: %0.1fC" % temperature
print "AM2315 from WXLink humidity: %0.1f%%" % humidity
# now read the SunAirPlus Data from WXLink
WXbatteryVoltage = struct.unpack('f', str(block2[1:5]))[0]
WXbatteryCurrent = -struct.unpack('f', str(block2[5:9]))[0]
WXloadCurrent = struct.unpack('f', str(block2[9:13]))[0]
WXsolarPanelVoltage = struct.unpack('f', str(block2[13:17]))[0]
WXsolarPanelCurrent = struct.unpack('f', str(block2[17:21]))[0]
WXbatteryPower = WXbatteryVoltage * (WXbatteryCurrent/1000)
WXsolarPower = WXsolarPanelVoltage * (WXsolarPanelCurrent/1000)
WXloadPower = 5.0 * (WXloadCurrent/1000)
WXbatteryCharge = util.returnPercentLeftInBattery(WXbatteryVoltage, 4.19)
state.WXbatteryVoltage = WXbatteryVoltage
state.WXbatteryCurrent = WXbatteryCurrent
state.WXloadCurrent = WXloadCurrent
state.WXsolarVoltage = WXsolarPanelVoltage
state.WXsolarCurrent = WXsolarPanelCurrent
state.WXbatteryPower = WXbatteryPower
state.WXsolarPower = WXsolarPower
state.WXloadPower = WXloadPower
state.WXbatteryCharge = WXbatteryCharge
auxA = struct.unpack('f', str(block2[21:25]))[0]
# now set state variables
if (config.SWDEBUG):
print "WXLink batteryVoltage = %6.2f" % WXbatteryVoltage
print "WXLink batteryCurrent = %6.2f" % WXbatteryCurrent
print "WXLink loadCurrent = %6.2f" % WXloadCurrent
print "WXLink solarPanelVoltage = %6.2f" % WXsolarPanelVoltage
print "WXLink solarPanelCurrent = %6.2f" % WXsolarPanelCurrent
print "WXLink auxA = %6.2f" % auxA
# message ID
MessageID = struct.unpack('l', str(block2[25:29]))[0]
print "WXLink Message ID %i" % MessageID
if (config.WXLink_LastMessageID != MessageID):
config.WXLink_Data_Fresh = True
config.WXLink_LastMessageID = MessageID
if (config.SWDEBUG):
print "WXLink_Data_Fresh set to True"
#
# use protocol 8 if SolarMAX_Present == True
#if (((protocol_ID == 8) or (protocol_ID == 10))and (config.SolarMAX_Present)):
if ((protocol_ID == SOLARMAXPROTOCOL) and (config.SolarMAX_Present)): # 3 is the WXLink Protocol
############################
############################
############################
############################
#print("protocol 8 or 9 - SolarMAX received")
print("protocol "+str(protocol_ID) +" SolarMAX received")
#print("protocol "+str(SOLARMAXPROTOCOL)+ " SolarMAX received")
############################
############################
############################
############################
# now do the inside Temperature in the SolarMAX
SolarMaxInsideTemperature = struct.unpack('f', str(block1[25:29]))[0]
if (config.SWDEBUG):
print "SMOTFloat=%x%x%x%x" %(block1[25], block1[26], block1[27], block1[28])
elements = [block1[29], block1[30], block1[31], block2[0]]
outHByte = bytearray(elements)
SolarMaxInsideHumidity = struct.unpack('f', str(outHByte))[0]
if (config.SWDEBUG):
print "ITemperature from SolarMAX temperature: %0.1fC" % SolarMaxInsideTemperature
print "IHumidity from SolarMAX humidity: %0.1f%%" % SolarMaxInsideHumidity
# now read the SolarMax Data from packet
SolarMaxloadVoltage = struct.unpack('f', str(block1[21:25]))[0]
SolarMaxbatteryVoltage = struct.unpack('f', str(block2[1:5]))[0]
SolarMaxbatteryCurrent = -struct.unpack('f', str(block2[5:9]))[0]
SolarMaxloadCurrent = struct.unpack('f', str(block2[9:13]))[0]
SolarMaxsolarPanelVoltage = struct.unpack('f', str(block2[13:17]))[0]
SolarMaxsolarPanelCurrent = -struct.unpack('f', str(block2[17:21]))[0]
SolarMaxbatteryPower = SolarMaxbatteryVoltage * (SolarMaxbatteryCurrent/1000)
SolarMaxsolarPower = SolarMaxsolarPanelVoltage * (SolarMaxsolarPanelCurrent/1000)
SolarMaxloadPower = SolarMaxloadVoltage * (SolarMaxloadCurrent/1000)
SolarMaxbatteryCharge = util.returnPercentLeftInBattery(SolarMaxbatteryVoltage, 4.19)
state.batteryVoltage = SolarMaxbatteryVoltage
state.batteryCurrent = SolarMaxbatteryCurrent
state.loadCurrent = SolarMaxloadCurrent
state.loadVoltage = SolarMaxloadVoltage
state.solarVoltage = SolarMaxsolarPanelVoltage
state.solarCurrent = SolarMaxsolarPanelCurrent
state.batteryPower = SolarMaxbatteryPower
state.solarPower = SolarMaxsolarPower
state.loadPower = SolarMaxloadPower
state.batteryCharge = SolarMaxbatteryCharge
state.SolarMaxInsideTemperature = SolarMaxInsideTemperature
state.SolarMaxInsideHumidity = SolarMaxInsideHumidity
auxA = struct.unpack('f', str(block2[21:25]))[0]
# now set state variables
if (config.SWDEBUG):
print "SolarMax batteryVoltage = %6.2f" % SolarMaxbatteryVoltage
print "SolarMax batteryCurrent = %6.2f" % SolarMaxbatteryCurrent
print "SolarMax loadVoltage = %6.2f" % SolarMaxloadVoltage
print "SolarMax loadCurrent = %6.2f" % SolarMaxloadCurrent
print "SolarMax solarPanelVoltage = %6.2f" % SolarMaxsolarPanelVoltage
print "SolarMax solarPanelCurrent = %6.2f" % SolarMaxsolarPanelCurrent
print "SolarMax auxA = %6.2f" % auxA
# message ID
MessageID = struct.unpack('l', str(block2[25:29]))[0]
print "SolarMax Message ID %i" % MessageID
if (config.SolarMAX_Present == True):
if (config.USEBLYNK):
if (config.WXLink_Data_Fresh == True):
if (config.SWDEBUG):
updateBlynk.blynkStatusTerminalUpdate("SolarMAX ID# %d received"%config.WXLink_LastMessageID)
entry = time.strftime("%Y-%m-%d %H:%M:%S")+": %i \n" % (MessageID)
state.SolarMAXLastReceived = entry
updateBlynk.blynkSolarMAXLine(entry,protocol_ID )
if ((protocol_ID == WXLINKPROTOCOLID) or (protocol_ID == 8) or (protocol_ID == 10)):
#if ((protocol_ID == WXLINKPROTOCOLID) or (protocol_ID == SOLARMAXPROTOCOL) ):
pass
else:
if (config.SWDEBUG):
print "unknown or non-configured protocol received. Protocol = ", protocol_ID
return []
else:
print "Bad CRC Received"
return []
else:
return []
# return list
if ((protocol_ID == WXLINKPROTOCOLID) and ((config.SolarMAX_Present == False) or (config.Dual_MAX_WXLink == True))): # 3 is the WXLink Protocol
returnList = []
returnList.append(protocol_ID)
returnList.append(block1_orig)
returnList.append(block2_orig)
returnList.append(currentWindSpeed)
returnList.append(currentWindGust)
returnList.append(totalRain)
returnList.append(currentWindDirection)
returnList.append(temperature)
returnList.append(humidity)
returnList.append(WXbatteryVoltage)
returnList.append(WXbatteryCurrent)
returnList.append(WXloadCurrent)
returnList.append(WXsolarPanelVoltage)
returnList.append(WXsolarPanelCurrent)
returnList.append(auxA)
returnList.append(MessageID)
else:
returnList = [] # protocol 8 - SolarMAX
returnList.append(protocol_ID)
return returnList
except Exception as e:
if (config.SWDEBUG):
print(traceback.format_exc())
print("LoRa Packet Decode Failure - probably short block receive")
print("e=",e)
return []
def readRawWXLink():
if state.ll.waitRX(timeout=5):
if (config.SWDEBUG):
print("after WXLink waitRX")
data=state.ll.recv()
header=data[0:4]
msg=data[4:]
#print('header: ',header)
#print('message:',array.array('B', msg).tostring())
#for i in range(0,len(data)):
# print('i={:d} {:d} 0x{:X}'.format( i,data[i],data[i]))
if (config.SWDEBUG):
print "-----------"
block1 = msg[0:32]
if (config.SWDEBUG):
print "block1=", block1
block2 = msg[32:65]
state.block1_orig = block1
state.block2_orig = block2
if (config.SWDEBUG):
print "block2=", block2
state.stringblock1 = ''.join(chr(e) for e in block1)
state.stringblock2 = ''.join(chr(e) for e in block2[0:27])
if (config.SWDEBUG):
print "-----------"
print "block 1"
print ''.join('{:02x}'.format(x) for x in block1)
state.block1 = bytearray(block1)
if (config.SWDEBUG):
print "block 2"
state.block2 = bytearray(block2)
if (config.SWDEBUG):
print ''.join('{:02x}'.format(x) for x in block2)
print "-----------"