Files
ThingsBoard/RPi Docker/python_firmware/drivers/tsac.py
2024-10-04 18:53:54 -05:00

589 lines
18 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 = "tsac" + '_[' + 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 = "4"
self.mqtt = mqtt
self.register()
#make the serial connection:
self.instrument = minimalmodbus.Instrument('/dev/ttyUSB4', 1) # port name, slave address (in decimal)
self.instrument.debug = True
self.instrument.serial.port # this is the serial port name
self.instrument.serial.parity = serial.PARITY_NONE
self.instrument.serial.xonxoff = False
self.instrument.serial.baudrate = 9600 # Baud
self.instrument.serial.bytesize = 8
self.instrument.serial.stopbits = 1
self.instrument.serial.timeout = 2 # seconds
self.instrument.address = 1
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.sendtodb("connected", "True", 0)
self.bitar1lst = ["em_stop_output", "comp_run_stat", "air_dis_valve_stat", "wireless1_com_er"]
self.bitar1 = {"em_stop_output": "", "comp_run_stat": "", "air_dis_valve_stat": "", "wireless1_com_er": ""}
self.bitarlst = ["CO", "CO2", "O2", "VOC", "dew_point", "temp_trans", "pres_trans", "flow_trans", "temp_wrls_nd1", "pres_wrls_nd1"]
self.bit_inhibits_status = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
self.bit_alarm_1 = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
self.bit_alarm_2 = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
self.bit_fault = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
self.bit_calibrate = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
self.bit_values = {"CO":"", "CO2":"", "O2":"", "VOC":"", "dew_point":"", "temp_trans":"", "pres_trans":"", "flow_trans":"", "temp_wrls_nd1":"", "pres_wrls_nd1":""}
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)
self.count = 3001
hb_count = 0
while not self.finished.isSet():
self.count += 1
try:
print "################################"
print "#############sending data ######"
try:
connected = int(self.mqtt._state)
if connected == 1:
pause = .1
else:
pause = 5
time.sleep(pause)
#get bitArray for compressor status
self.firstArray()
time.sleep(pause)
self.inhibitArray()
time.sleep(pause)
self.alarm1Array()
time.sleep(pause)
self.alarm2Array()
time.sleep(pause)
self.faultArray()
time.sleep(pause)
self.calArray()
time.sleep(pause)
#read these registers for the float values
regList = [7, 9, 11, 13, 15, 17, 19, 21, 23, 25]
for i in range(10):
val = ""
val = self.instrument.read_float(regList[i], functioncode=3)
val = round(val, 1)
if val != self.bit_values[self.bitarlst[i]]:
self.sendtodb((self.bitarlst[i] + "_val"), val, 0)
self.bit_values[self.bitarlst[i]] = val
last_O2 = self.alarmsStr("O2", self.last_O2_alarms)
self.last_O2_alarms = last_O2
last_CO = self.alarmsStr("CO", self.last_CO_alarms)
self.last_CO_alarms = last_CO
last_CO2 = self.alarmsStr("CO2", self.last_CO2_alarms)
self.last_CO2_alarms = last_CO2
last_VOC = self.alarmsStr("VOC", self.last_VOC_alarms)
self.last_VOC_alarms = last_VOC
hb_count += 1
if hb_count > 600:
hb_count = 0
self.sendtodb("hb", "1", 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))
# internal functions & classes
def alarmsStr(self, gas, lastValue):
msg = ""
alarm1 = self.bit_alarm_1[gas]
alarm2 = self.bit_alarm_2[gas]
fault = self.bit_fault[gas]
inhib = self.bit_inhibits_status[gas]
if int(alarm1) == 1:
msg += "Alarm 1, "
if int(alarm2) == 1:
msg += "Alarm 2, "
if int(fault) == 1:
msg += "Fault, "
if int(inhib) == 1:
msg += "Inhibited, "
if msg == "":
msg = "No Alarms"
if msg != lastValue:
if lastValue == "No Alarms" or lastValue == "":
if msg != "No Alarms":
#changed from no alarms to alarms, alarm state is On
chName = (gas + "_alm_st")
self.sendtodb(chName, "On", 0)
if lastValue != "No Alarms" or lastValue == "":
if msg == "No Alarms":
#changed from alarms to no alarms, alarm state is Off
chName = (gas + "_alm_st")
self.sendtodb(chName, "Off", 0)
name = "alarms_" + gas
if msg != lastValue:
self.sendtodb(name, msg, 0)
return msg
def calArray(self):
array = self.getBitArray(6)
for i in range(4):
if array[i] != self.bit_calibrate[self.bitarlst[i]]:
if array[i] == '0':
val = "Normal"
elif array[i] == '1':
val = "Calibration Mode"
else:
continue
self.sendtodb((self.bitarlst[i] + "_cal"), val, 0)
self.bit_calibrate[self.bitarlst[i]] = array[i]
def faultArray(self):
array = self.getBitArray(5)
for i in range(10):
if array[i] != self.bit_fault[self.bitarlst[i]]:
if array[i] == '0':
val = "Off"
elif array[i] == '1':
val = "On"
else:
continue
self.sendtodb((self.bitarlst[i] + "_flt"), val, 0)
self.bit_fault[self.bitarlst[i]] = array[i]
def alarm2Array(self):
array = self.getBitArray(4)
for i in range(10):
if array[i] != self.bit_alarm_2[self.bitarlst[i]]:
if array[i] == '0':
val = "Off"
elif array[i] == '1':
val = "On"
else:
continue
self.sendtodb((self.bitarlst[i] + "_a2"), val, 0)
self.bit_alarm_2[self.bitarlst[i]] = array[i]
def alarm1Array(self):
array = self.getBitArray(3)
for i in range(10):
if array[i] != self.bit_alarm_1[self.bitarlst[i]]:
if array[i] == '0':
val = "Off"
elif array[i] == '1':
val = "On"
else:
continue
self.sendtodb((self.bitarlst[i] + "_a1"), val, 0)
self.bit_alarm_1[self.bitarlst[i]] = array[i]
def inhibitArray(self):
array = self.getBitArray(2)
for i in range(10):
if array[i] != self.bit_inhibits_status[self.bitarlst[i]]:
if array[i] == '0':
val = "OK"
elif array[i] == '1':
val = "Inhibited"
else:
continue
self.sendtodb((self.bitarlst[i] + "_inhib"), val, 0)
self.bit_inhibits_status[self.bitarlst[i]] = array[i]
def firstArray(self):
array = self.getBitArray(1)
for i in range(4):
if array[i] != self.bitar1[self.bitar1lst[i]]:
if i == 0:
if array[i] == '0':
val = "Off"
elif array[i] == '1':
val = "On"
else:
continue
if i == 1:
if array[i] == '0':
val = "Off"
elif array[i] == '1':
val = "Running"
else:
continue
if i == 2:
if array[i] == '0':
val = "Closed"
elif array[i] == '1':
val = "Open"
else:
continue
if i == 3:
if array[i] == '0':
val = "OK"
elif array[i] == '1':
val = "Com Error"
else:
continue
self.sendtodb(self.bitar1lst[i], val, 0)
self.bitar1[self.bitar1lst[i]] = array[i]
def getBitArray(self, address):
lst = self.instrument.read_register(int(address), functioncode=3)
lst = int(lst)
lst = hex(lst)
lst = lst[2:]
while len(lst) < 4:
lst = "0" + lst
bit1 = lst[0:2]
bit2 = lst[2:]
bit1 = int(bit1, 16)
bit2 = int(bit2, 16)
lst1 = list('{0:0b}'.format(bit1))
lst2 = list('{0:0b}'.format(bit2))
while len(lst1) < 8:
lst1 = ['0'] + lst1
while len(lst2) < 8:
lst2 = ['0'] + lst2
lst = lst2 + lst1
lst = lst[::-1]
print lst
return lst
def tsac_sync(self, name, value):
self.register()
self.count = 3001
return True
def tsac_signal(self, name, value):
self.signal()
return True
def tsac_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)))