Files
ThingsBoard/RPI Docker Test/drivers/arae.py
2024-10-04 18:53:54 -05:00

472 lines
16 KiB
Python

import types
import traceback
import binascii
import threading
import time
import thread
import os
import struct
import sys
import serial
import minimalmodbus
import pickle
_NUMBER_OF_BYTES_PER_REGISTER = 2
class start(threading.Thread):
"""\
This class extends one of our base classes and is intended as an
example of a concrete, example implementation, but it is not itself
meant to be included as part of our developer API. Please consult the
base class documentation for the API and the source code for this file
for an example implementation.
"""
# here are the setting defaults
DEF_HEXDEC = True
DEF_EOLN = None
DEF_CHARTOUT = 2.0
# a sanity value to prevent an infinite rcv_buffer creation
DEF_MAX_READ = 1000
def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None):
threading.Thread.__init__(self)
self.daemon = True
self.offset = offset
self.company = companyId
self.name = name
self.number = number
self.q = Q
self.deviceName = name + '_[' + mac + ':' + number[0:2] + ':' + number[2:] + ']!'
self.chName = "tsar" + '_[' + mac + ':'
print 'device name is:'
print self.deviceName
mac2 = mac.replace(":", "")
self.mac = mac2.upper()
self.address = 1
self.debug = True
self.mcu = mcu
self.firstRun = True
self.version = "10"
self.mqtt = mqtt
self.register()
self.finished = threading.Event()
threading.Thread.start(self)
#this is a required function for all drivers, its goal is to upload some piece of data
#about your device so it can be seen on the web
def register(self):
self.areaRaeDict = {
1:{"sendString":"\xf1\x03\x01\x01\x0a", "last_CO":"", "last_VOC":"","last_H2S":"","last_LEL":"","last_O2":"", "last_address":"", "connected": "", "badReadCount": -1},
2:{"sendString":"\xf1\x03\x02\x01\x09", "last_CO":"", "last_VOC":"","last_H2S":"","last_LEL":"","last_O2":"", "last_address":"", "connected": "", "badReadCount": -1},
4:{"sendString":"\xf1\x03\x04\x01\x07", "last_CO":"", "last_VOC":"","last_H2S":"","last_LEL":"","last_O2":"", "last_address":"", "connected": "", "badReadCount": -1}
}
self.lastLong = ""
self.lastLat = ""
self.last_CO_alarms = ""
self.last_CO2_alarms = ""
self.last_O2_alarms = ""
self.last_VOC_alarms = ""
self.count = 3001
def stop (self):
self.finished.set()
self.join()
def sendtodbCH(self, ch, channel, value, timestamp):
if int(ch) < 10:
ch = "0" + str(ch)
dname = self.chName + str(ch) + ":99]!"
if int(timestamp) == 0:
timestamp = self.getTime()
topic = 'meshify/db/%s/%s/%s/%s' % (self.company, self.mac, dname, channel)
print topic
msg = """[ { "value":"%s", "timestamp":"%s" } ]""" % (str(value), str(timestamp))
print msg
self.q.put([topic, msg, 0])
def sendtodb(self, channel, value, timestamp):
if int(timestamp) == 0:
timestamp = self.getTime()
if timestamp < 1400499858:
return
topic = 'meshify/db/%s/%s/%s/%s' % (self.company, self.mac, self.deviceName, channel)
print topic
msg = """[ { "value":"%s", "timestamp":"%s" } ]""" % (str(value), str(timestamp))
print msg
self.q.put([topic, msg, 0])
def start(self):
# you could add other ddo settings here
thread.start_new_thread(self.loop, ())
# def stop(): uses XBeeSerial.stop()
## Locally defined functions:
def gps(self):
try:
resp = False
ser = serial.Serial(port='/dev/ttyS3', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, xonxoff=False)
ser.open
time.sleep(2)
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
time.sleep(1)
response = ser.readline()
print response
latNeg = ""
longNeg = ""
if response.split(',')[0] == "$GPRMC":
lat = response.split(',')[3]
if response.split(',')[4] == "S":
latNeg = "-"
longitude = response.split(',')[5]
if response.split(',')[6] == "W":
longNeg = "-"
elif response.split(',')[0] == "$GPGGA":
lat = response.split(',')[2]
if response.split(',')[3] == "S":
latNeg = "-"
longitude = response.split(',')[4]
if response.split(',')[5] == "W":
longNeg = "-"
else:
return
googlelat = (latNeg + str(((int(lat.split(".")[0][:2])) + ( float(((lat.split(".")[0][-2:]) + "." + lat.split(".")[1])) / 60) )))
googlelong = (longNeg + str(((int(longitude.split(".")[0][:3])) + ( float(((longitude.split(".")[0][-2:]) + "." + longitude.split(".")[1])) / 60) )))
googlelat = str(round(float(googlelat), 4))
googlelong = str(round(float(googlelong), 4))
if googlelat != self.lastLat or googlelong != self.lastLong:
print googlelat, googlelong
value = googlelat + "," + googlelong
if value != "24.0,121.0" and value!= "0.0,0.0":
resp = True
self.sendtodb("gps", value, 0)
else:
resp = False
self.lastLat = googlelat
self.lastLong = googlelong
ser.close()
return resp
except Exception,e:
print e
try:
ser.close()
except:
pass
pass
def signal(self):
try:
ser = serial.Serial(port='/dev/modem_at1', timeout=2, baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, xonxoff=False)
ser.open
time.sleep(2)
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput()#flush output buffer, aborting current output
time.sleep(.5)
ser.write("AT+CSQ" + chr(13))
print("write data: AT+CSQ")
time.sleep(0.5)
response = ser.readlines()
response = response[1].split(",")[0].replace("+CSQ:", "").strip()
response = (-113 + (int(response) * 2))
print response
ser.close()
self.sendtodb("signal", str(response), 0)
except:
try:
ser.close()
except:
pass
pass
def checkTemp(self):
temp = os.popen('/usr/sbin/mts-io-sysfs show board-temperature')
temp1 = temp.read()
temp1 = temp1.strip()
self.sendtodb("temp", temp1, 0)
temp.close()
def run(self):
#on startup send the version number
self.sendtodb("version", str(self.version), 0)
self.sendtodb("log", "system start up", 0)
while True:
try:
self.ser =serial.Serial(port='/dev/ttyUSB4', baudrate=19200, bytesize=8, parity='N', stopbits=1, timeout=0.5, xonxoff=0, rtscts=True, dsrdtr=True)
break
except:
self.sendtodb("error", "cant open com port on AreaRae", 0)
time.sleep(5)
self.count = 3001
hb_count = 0
localCount = 0
while not self.finished.isSet():
self.count += 1
try:
try:
for channel in self.areaRaeDict:
dict = self.areaRaeDict[channel]
#check and see if we need to call the state disconnected or connected
if dict["badReadCount"] == 0:
connected = "True"
if connected != dict["connected"]:
self.sendtodbCH(channel, "connected", connected, 0)
dict["connected"] = connected
elif dict["badReadCount"] > 15:
connected = "False"
if connected != dict["connected"]:
self.sendtodbCH(channel, "connected", connected, 0)
dict["connected"] = connected
else:
pass
sendString = dict["sendString"]
last_CO = dict["last_CO"]
last_VOC = dict["last_VOC"]
last_H2S = dict["last_H2S"]
last_LEL = dict["last_LEL"]
last_O2 = dict["last_O2"]
last_address = dict["last_address"]
#update all values every 600 loops
localCount += 1
if localCount > 120:
localCount = 0
last_CO = ""
last_VOC = ""
last_H2S = ""
last_LEL = ""
last_O2 = ""
self.ser.write(sendString)
#time.sleep(.5)
data = self.ser.read(48)
lst2 = map(hex,map(ord,data))
try:
if (len(lst2) -2) != int(lst2[1], 16):
print "data wrong length"
dict["badReadCount"] = dict["badReadCount"] + 2
continue
address = [lst2[9].replace('0x', ''), lst2[8].replace('0x', ''), lst2[7].replace('0x', ''), lst2[6].replace('0x', ''), lst2[5].replace('0x', '')]
mac = ""
for i in address:
print len(i)
while len(i) < 2:
i = "0" + i
mac += (i + ":")
mac = mac[:-1]
print mac
print " "
print "CO: ", (float(int((lst2[16]+lst2[15].replace('0x', '')), 16)) / 10)
print "VOC: ", (float(int((lst2[23]+lst2[22].replace('0x', '')), 16)) / 10)
print "H2S: ", (float(int((lst2[30]+lst2[29].replace('0x', '')), 16)) / 10)
print "LEL: ", (float(int((lst2[37]+lst2[36].replace('0x', '')), 16)) / 10)
print "O2: ", (float(int((lst2[44]+lst2[43].replace('0x', '')), 16)) / 10)
CO = (float(int((lst2[16]+lst2[15].replace('0x', '')), 16)) / 10)
VOC = (float(int((lst2[23]+lst2[22].replace('0x', '')), 16)) / 10)
H2S = (float(int((lst2[30]+lst2[29].replace('0x', '')), 16)) / 10)
LEL = (float(int((lst2[37]+lst2[36].replace('0x', '')), 16)) / 10)
O2 = (float(int((lst2[44]+lst2[43].replace('0x', '')), 16)) / 10)
#assume if we get here that we have a good connection
dict["badReadCount"] = 0
if CO < 1.5:
CO = 0
if VOC < 1.0:
VOC = 0
if H2S < 1.0:
H2S = 0
if LEL < 1.0:
LEL = 0
if O2 < 1.0:
O2 = 0
if CO != last_CO:
self.sendtodbCH(channel, "CO", CO, 0)
self.areaRaeDict[channel]["last_CO"] = CO
if VOC != last_VOC:
self.sendtodbCH(channel, "VOC", VOC, 0)
self.areaRaeDict[channel]["last_VOC"] = VOC
if H2S != last_H2S:
self.sendtodbCH(channel, "H2S", H2S, 0)
self.areaRaeDict[channel]["last_H2S"] = H2S
if LEL != last_LEL:
self.sendtodbCH(channel, "LEL", LEL, 0)
self.areaRaeDict[channel]["last_LEL"] = LEL
if O2 != last_O2:
self.sendtodbCH(channel, "O2", O2, 0)
self.areaRaeDict[channel]["last_O2"] = O2
if last_address != last_address:
self.sendtodbCH(channel, "id", mac, 0)
self.areaRaeDict[channel]["last_address"] = mac
except Exception,e:
print e
dict["badReadCount"] = dict["badReadCount"] + 2
print "Response too short"
hb_count += 1
if hb_count > 600:
hb_count = 0
self.sendtodb("hb", "On", 0)
except Exception,e: print(str(e))
if self.count > 3000:
self.count = 0
try:
#self.gps()
#self.signal()
self.checkTemp()
except:
pass
except Exception,e: print(str(e))
def arae_sync(self, name, value):
self.register()
self.count = 3001
return True
def arae_signal(self, name, value):
self.signal()
return True
def arae_udgps(self, name, value):
self.lastLong = ""
self.lastLat = ""
resp = self.gps()
if resp == False:
self.sendtodb("log", "gps lock failed", 0)
else:
self.sendtodb("log", "gps lock success", 0)
return True
def get_eoln(self):
eoln = SettingsBase.get_setting(self, "eoln")
if eoln is None:
return None
if eoln != self.__eoln_save:
# cache result to avoid repeat processing of escapes
self.__eoln_save = eoln
self._eoln = strip_escapes(eoln)
return self._eoln
def getTime(self):
return str(int(time.time() + int(self.offset)))