#!/usr/bin/python import threading import time from device_base import deviceBase import micro800 as u800 channels = {} addr = '192.168.1.40' class Channel(): def read(self): valData = u800.readMicroTag(self.device_addr, self.tag) if valData: nowVal = valData[0] if self.map_obj: nowVal = self.map_obj[nowVal] self.data_type = valData[1] if self.data_type == "BOOL" or self.map_obj: if self.last_value == "": self.sendFn(self.name, nowVal, 0) self.last_time_uploaded = time.time() self.last_value = nowVal elif (not (self.last_value == nowVal)) or ((time.time() - self.last_time_uploaded) > self.max_time_between_uploads): self.sendFn(self.name, nowVal, 0) self.last_time_uploaded = time.time() self.last_value = nowVal elif (self.data_type == "REAL") or (self.data_type[-3:] == "INT"): if self.last_value == "": self.sendFn(self.name, nowVal, 0) self.last_time_uploaded = time.time() self.last_value = nowVal elif (abs(self.last_value - nowVal) > self.change_threshold) or ((time.time() - self.last_time_uploaded) > self.max_time_between_uploads): self.sendFn(self.name, nowVal, 0) self.last_time_uploaded = time.time() self.last_value = nowVal return True return False def __init__(self, name, tag, max_time_between_uploads, sendFn, change_threshold=0.0, writeable=False, map_obj=None): global addr self.name = name self.tag = tag self.data_type = '' self.last_value = '' self.last_time_uploaded = 0 self.change_threshold = change_threshold self.max_time_between_uploads = int(max_time_between_uploads) self.sendFn = sendFn self.device_addr = addr self.writeable = bool(writeable) self.map_obj = map_obj self.read() def write(self, val, handshake=None, handshake_val=None): if self.writeable: h = handshake hval = handshake_val if h is None: if u800.writeMicroTag(self.device_addr, self.tag, val): self.sendFn(self.name, val, time.time()) self.last_value = val return True else: return False else: return u800.writeMicroTag(self.device_addr, self.tag, val, handshake=h, handshake_val=hval) else: print("NOT ALLOWED TO WRITE TO {}".format(self.name)) return False class start(threading.Thread, deviceBase): def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None): global addr, channels threading.Thread.__init__(self) deviceBase.__init__(self, name=name, number=number, mac=mac, Q=Q, mcu=mcu, companyId=companyId, offset=offset, mqtt=mqtt, Nodes=Nodes) print("!!! Made it to Driver init() !!!") self.daemon = True self.version = "3" self.finished = threading.Event() threading.Thread.start(self) self.last_channel_send = 0 self.device_address = addr def setupChannels(self): global channels channels = { 'alarmengineoilpressurehifault': Channel('alarmengineoilpressurehifault', 'alarm_EngineOilPressure_HiFault', 360, self.sendtodbJSON, writeable=False), 'alarmengineoilpressurelofault': Channel('alarmengineoilpressurelofault', 'alarm_EngineOilPressure_LoFault', 360, self.sendtodbJSON, writeable=False), 'alarmhydraulicfluidtemphifault': Channel('alarmhydraulicfluidtemphifault', 'alarm_HydraulicFluidTemp_HiFault', 360, self.sendtodbJSON, writeable=False), 'alarmhydraulicpressurehifault': Channel('alarmhydraulicpressurehifault', 'alarm_HydraulicPressure_HiFault', 360, self.sendtodbJSON, writeable=False), 'alarminvalidstate': Channel('alarminvalidstate', 'alarm_InvalidState', 360, self.sendtodbJSON, writeable=False), 'alarmmotorstartuptimeout': Channel('alarmmotorstartuptimeout', 'alarm_MotorStartupTimeout', 360, self.sendtodbJSON, writeable=False), 'alarmstrokeoverlap': Channel('alarmstrokeoverlap', 'alarm_StrokeOverlap', 360, self.sendtodbJSON, writeable=False), 'alarmtimeoutduringlifting': Channel('alarmtimeoutduringlifting', 'alarm_TimeoutDuringLifting', 360, self.sendtodbJSON, writeable=False), 'cfgcylinderid': Channel('cfgcylinderid', 'cfg_CylinderID', 360, self.sendtodbJSON, change_threshold=0.5, writeable=True), 'cfgenginehourswarning': Channel('cfgenginehourswarning', 'cfg_EngineHours_Warning', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgengineoilpressureeumax': Channel('cfgengineoilpressureeumax', 'cfg_EngineOilPressure_EUMax', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgengineoilpressureeumin': Channel('cfgengineoilpressureeumin', 'cfg_EngineOilPressure_EUMin', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgengineoilpressurehifault': Channel('cfgengineoilpressurehifault', 'cfg_EngineOilPressure_HiFault', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgengineoilpressurelofault': Channel('cfgengineoilpressurelofault', 'cfg_EngineOilPressure_LoFault', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgenginerunningoilpressure': Channel('cfgenginerunningoilpressure', 'cfg_EngineRunning_OilPressure', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgfaultedmotorshutdownmins': Channel('cfgfaultedmotorshutdownmins', 'cfg_FaultedMotorShutdownMins', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidcoolerenabled': Channel('cfghydfluidcoolerenabled', 'cfg_HydFluidCooler_Enabled', 360, self.sendtodbJSON, writeable=True), 'cfghydfluidcoolertempoff': Channel('cfghydfluidcoolertempoff', 'cfg_HydFluidCooler_TempOff', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidcoolertempon': Channel('cfghydfluidcoolertempon', 'cfg_HydFluidCooler_TempOn', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidtempeumax': Channel('cfghydfluidtempeumax', 'cfg_HydFluidTemp_EUMax', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidtempeumin': Channel('cfghydfluidtempeumin', 'cfg_HydFluidTemp_EUMin', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidtemphifault': Channel('cfghydfluidtemphifault', 'cfg_HydFluidTemp_HiFault', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidtemphiwarning': Channel('cfghydfluidtemphiwarning', 'cfg_HydFluidTemp_HiWarning', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydfluidtemphiwarningmultiplier': Channel('cfghydfluidtemphiwarningmultiplier', 'cfg_HydFluidTemp_HiWarningMultiplier', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydpressclosesp': Channel('cfghydpressclosesp', 'cfg_HydPress_CloseSP', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydpresseumax': Channel('cfghydpresseumax', 'cfg_HydPress_EUMax', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydpresseumin': Channel('cfghydpresseumin', 'cfg_HydPress_EUMin', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydpresshifault': Channel('cfghydpresshifault', 'cfg_HydPress_HiFault', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfghydpressliftingsp': Channel('cfghydpressliftingsp', 'cfg_HydPress_LiftingSP', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgliftingtimetimeout': Channel('cfgliftingtimetimeout', 'cfg_LiftingTimeTimeout', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgpolishedrodod': Channel('cfgpolishedrodod', 'cfg_PolishedRodOD', 360, self.sendtodbJSON, change_threshold=0.01, writeable=True), 'cfgspmtarget': Channel('cfgspmtarget', 'cfg_SPMTarget', 360, self.sendtodbJSON, change_threshold=0.001, writeable=True), 'cmdengineresethourmeter': Channel('cmdengineresethourmeter', 'cmd_EngineResetHourMeter', 360, self.sendtodbJSON, writeable=True), 'cmdenginestart': Channel('cmdenginestart', 'cmd_EngineStart', 360, self.sendtodbJSON, writeable=True), 'cmdenginestop': Channel('cmdenginestop', 'cmd_EngineStop', 360, self.sendtodbJSON, writeable=True), 'cmdresetfault': Channel('cmdresetfault', 'cmd_ResetFault', 360, self.sendtodbJSON, writeable=True), 'cmdresetstrokelifetime': Channel('cmdresetstrokelifetime', 'cmd_ResetStrokeLifetime', 360, self.sendtodbJSON, writeable=True), 'cmdrun': Channel('cmdrun', 'cmd_Run', 360, self.sendtodbJSON, writeable=False), 'cmdstart': Channel('cmdstart', 'cmd_Start', 360, self.sendtodbJSON, writeable=True), 'cmdstop': Channel('cmdstop', 'cmd_Stop', 360, self.sendtodbJSON, writeable=True), 'countstrokelifetime': Channel('countstrokelifetime', 'count_StrokeLifetime', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'countstrokestartup': Channel('countstrokestartup', 'count_StrokeStartup', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'countstroketoday': Channel('countstroketoday', 'count_StrokeToday', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'outenginestart': Channel('outenginestart', 'out_EngineStart', 360, self.sendtodbJSON, writeable=False), 'outenginestop': Channel('outenginestop', 'out_EngineStop', 360, self.sendtodbJSON, writeable=False), 'outhydfluidcooler': Channel('outhydfluidcooler', 'out_HydFluidCooler', 360, self.sendtodbJSON, writeable=False), 'rpallok': Channel('rpallok', 'rp_AllOK', 360, self.sendtodbJSON, writeable=False), 'rpengine': Channel('rpengine', 'rp_Engine', 360, self.sendtodbJSON, writeable=False), 'spallok': Channel('spallok', 'sp_AllOK', 360, self.sendtodbJSON, writeable=False), 'spengine': Channel('spengine', 'sp_Engine', 360, self.sendtodbJSON, writeable=False), 'stsautomode': Channel('stsautomode', 'sts_AutoMode', 360, self.sendtodbJSON, writeable=False), 'stsenginehourswarning': Channel('stsenginehourswarning', 'sts_EngineHours_Warning', 360, self.sendtodbJSON, writeable=False), 'stsengineint': Channel('stsengineint', 'sts_EngineINT', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False, map_obj={0: 'Stopped', 1: 'Starting', 2: 'Running', 3: 'Stopping'}), 'stsengineoilpressurehifault': Channel('stsengineoilpressurehifault', 'sts_EngineOilPressure_HiFault', 360, self.sendtodbJSON, writeable=False), 'stsengineoilpressurelofault': Channel('stsengineoilpressurelofault', 'sts_EngineOilPressure_LoFault', 360, self.sendtodbJSON, writeable=False), 'stsenginerunning': Channel('stsenginerunning', 'sts_EngineRunning', 360, self.sendtodbJSON, writeable=False), 'stserrorcodeint': Channel('stserrorcodeint', 'sts_ErrorCode_INT', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False, map_obj={0: 'No Error', 1: 'Motor Startup Timeout', 2: 'Stroke Overlap', 3: 'Timeout During Lifting', 4: 'Invalid State', 5: 'Lost Run Permissive', 6: 'Lost Engine Run Permissive'}), 'stshydraulicfluidtemphifault': Channel('stshydraulicfluidtemphifault', 'sts_HydraulicFluidTemp_HiFault', 360, self.sendtodbJSON, writeable=False), 'stshydraulicfluidtemphiwarning': Channel('stshydraulicfluidtemphiwarning', 'sts_HydraulicFluidTemp_HiWarning', 360, self.sendtodbJSON, writeable=False), 'stshydraulicpressurehifault': Channel('stshydraulicpressurehifault', 'sts_HydraulicPressure_HiFault', 360, self.sendtodbJSON, writeable=False), 'stsmanualmode': Channel('stsmanualmode', 'sts_ManualMode', 360, self.sendtodbJSON, writeable=False), 'stsstep': Channel('stsstep', 'sts_Step', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False, map_obj={0: 'Engine Off', 1: 'Engine Startup', 2: 'Engine Idle', 3: 'Lifting', 4: 'Falling', 5: 'Faulted', 6: 'IO Test', 7: 'Manual Operation'}), 'ststestmode': Channel('ststestmode', 'sts_TestMode', 360, self.sendtodbJSON, writeable=False), 'timeenginehourmeter': Channel('timeenginehourmeter', 'time_EngineHourMeter', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'timelastfallingtime': Channel('timelastfallingtime', 'time_LastFallingTime', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'timelastliftingtime': Channel('timelastliftingtime', 'time_LastLiftingTime', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'timesecondsperstroke': Channel('timesecondsperstroke', 'time_SecondsPerStroke', 360, self.sendtodbJSON, change_threshold=0.5, writeable=False), 'valengineoilpressure': Channel('valengineoilpressure', 'val_EngineOilPressure', 360, self.sendtodbJSON, change_threshold=2.0, writeable=False), 'valhydraulicfluidtemp': Channel('valhydraulicfluidtemp', 'val_HydraulicFluidTemp', 360, self.sendtodbJSON, change_threshold=2.0, writeable=False) # 'valhydraulicpressure': Channel('valhydraulicpressure', 'val_HydraulicPressure', 360, self.sendtodbJSON, change_threshold=2.0, writeable=False), # 'valpolishedrodload': Channel('valpolishedrodload', 'val_PolishedRodLoad', 360, self.sendtodbJSON, change_threshold=5.0, writeable=False), } def register(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 self.channels["status"]["last_value"] = "" def readChannelData(self): global channels print "Executing readChannelData()" runLoopStatus = "" try: for i in channels: runLoopStatus = i channels[i].read() runLoopStatus = "Complete" return True except Exception, e: print "Error during {0} of run loop: {1}".format(runLoopStatus, e) return False def checkLifting(self): return u800.readMicroTag(self.device_address, 'sts_Step')[0] == 3 def checkFalling(self): return u800.readMicroTag(self.device_address, 'sts_Step')[0] == 4 def checkIdle(self): s = u800.readMicroTag(self.device_address, 'sts_Step')[0] return not (s == 3) and not (s == 4) def run(self): global channels self.sendLastStroke = True self.sendCardEvery = 5 cardScanIndex = 0 PRLoadPoints = [] status = "" self.setupChannels() print("!!! Made it to Driver run() !!!") while True: if self.checkLifting(): # hydPressurePoints.append([time.time(), u800.readMicroTag(addr, 'val_HydraulicPressure')[0]]) PRLoadPoints.append([time.time(), u800.readMicroTag(addr, 'val_PolishedRodLoad')[0]]) if not status == "lifting": status = "lifting" self.sendtodbJSON('stsstep', 'Lifting', time.time()) print(status) elif self.checkFalling(): # hydPressurePoints.append([time.time(), u800.readMicroTag(addr, 'val_HydraulicPressure')[0]]) PRLoadPoints.append([time.time(), u800.readMicroTag(addr, 'val_PolishedRodLoad')[0]]) if not status == "falling": status = "falling" self.sendtodbJSON('stsstep', 'Falling', time.time()) print(status) elif self.checkIdle(): if not status == "idle": status = "idle" print(status) cardScanIndex = cardScanIndex + 1 if cardScanIndex == self.sendCardEvery: self.sendLastStroke = True cardScanIndex = 0 if self.sendLastStroke: pr_load_string = "[" for x in PRLoadPoints: pr_load_string = pr_load_string + "[{0},{1}],".format(x[0], x[1]) pr_load_string = pr_load_string[:-1] + "]" # hyd_press_string = "[" # for y in PRLoadPoints: # hyd_press_string = hyd_press_string + "[{0},{1}],".format(y[0], y[1]) # hyd_press_string = hyd_press_string[:-1] + "]" if len(PRLoadPoints) > 0: self.sendtodbJSON('polishedrodloadcard', pr_load_string, time.time()) # self.sendtodbJSON('hydraulicpressurecard', hyd_press_string, time.time()) self.sendLastStroke = False PRLoadPoints = [] self.readChannelData() self.last_channel_send = time.time() elif (time.time() - self.last_channel_send) > 10.0: print('Checking channel data') self.readChannelData() self.last_channel_send = time.time() time.sleep(0.1) def henryhyd_sync(self, name, value): self.sendtodb("connected", "true", 0) return True def genericSet(self, name, value, id): try: global channels print("Trying to set {} to {} (type {})".format(channels[name].tag, value)) return channels[name].write(value) except Exception, e: print("Exception during genericSet: {}".format(e)) def henryhyd_cmdengineresethourmeter(self, name, value): global channels print('trying to set cmd_EngineResetHourMeter to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="val_EngineHourMeter", handshake_val=0): self.sendtodb('valenginehourmeter', 0, time.time()) channels['valenginehourmeter'].last_value = 0 channels['valenginehourmeter'].last_time_uploaded = time.time() return True return False else: return channels[name].write(value) def henryhyd_cmdenginestart(self, name, value): global channels print('trying to set cmd_EngineStart to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="sts_EngineRunning", handshake_val=1): self.sendtodb('stsenginerunning', 1, time.time()) channels['stsenginerunning'].last_value = 1 channels['stsenginerunning'].last_time_uploaded = time.time() return True return False else: return channels[name].write(value) def henryhyd_cmdenginestop(self, name, value): global channels print('trying to set cmd_EngineStop to {} for {}'.format(value, addr)) if int(value) == 1: if channels[name].write(int(value), handshake="sts_EngineRunning", handshake_val=0): self.sendtodb('stsenginerunning', 0, time.time()) channels['stsenginerunning'].last_value = 0 channels['stsenginerunning'].last_time_uploaded = time.time() return True return False else: return channels[name].write(value) def henryhyd_cmdresetfault(self, name, value): global channels print('trying to set cmd_ResetFault to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="sts_ErrorCode_INT", handshake_val=0): self.sendtodb('stserrorcodeint', "No Error", time.time()) channels['stserrorcodeint'].last_value = 0 channels['stserrorcodeint'].last_time_uploaded = time.time() return True return False else: return channels[name].write(value) def henryhyd_cmdresetstrokelifetime(self, name, value): global channels print('trying to set cmd_ResetStrokeLifetime to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="count_StrokeLifetime", handshake_val=0): self.sendtodb('countstrokelifetime', 0, time.time()) channels['countstrokelifetime'].last_value = 0 channels['countstrokelifetime'].last_time_uploaded = time.time() return True return False else: return channels[name].write(value) def henryhyd_cmdstart(self, name, value): global channels print('trying to set cmd_Start to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="cmd_Run", handshake_val=1): self.sendtodb("cmdrun", 1, time.time()) channels['cmdrun'].last_value = 1 channels['cmdrun'].last_time_uploaded = time.time() return True else: return "Error while attempting to start" else: return channels[name].write(value) def henryhyd_cmdstop(self, name, value): global channels print('trying to set cmd_Stop to {}'.format(value)) if int(value) == 1: if channels[name].write(int(value), handshake="cmd_Run", handshake_val=0): self.sendtodb("cmdrun", 0, time.time()) channels['cmdrun'].last_value = 0 channels['cmdrun'].last_time_uploaded = time.time() return True else: return "Error while attempting to stop." else: return channels[name].write(value)