Added alerts and removed unmarshalling
This commit is contained in:
@@ -5,18 +5,19 @@ from pycomm.ab_comm.clx import Driver as clx
|
|||||||
from pycomm.cip.cip_base import CommError, DataError
|
from pycomm.cip.cip_base import CommError, DataError
|
||||||
|
|
||||||
class DataPoint(object):
|
class DataPoint(object):
|
||||||
def __init__(self,changeThreshold=0,guaranteed=3600, name="datapoint",alertThreshold=[],alertCondition=[],alertResponse=[],alertContact=[]):
|
def __init__(self,changeThreshold=0,guaranteed=3600, name="datapoint",alertThreshold=[],alertCondition=[],alertResponse=[],alertContact=[], alertName=[]):
|
||||||
self.value = None
|
self.value = None
|
||||||
self.lastvalue = None
|
self.lastvalue = None
|
||||||
self.lastsend = 0
|
self.lastsend = 0
|
||||||
self.changeThreshold = changeThreshold
|
self.changeThreshold = changeThreshold
|
||||||
self.guaranteed = guaranteed
|
self.guaranteed = guaranteed
|
||||||
self.name = name
|
self.name = name
|
||||||
self.alerted = False
|
|
||||||
self.alertThreshold = alertThreshold
|
self.alertThreshold = alertThreshold
|
||||||
self.alertCondition = alertCondition
|
self.alertCondition = alertCondition
|
||||||
self.alertResponse = alertResponse
|
self.alertResponse = alertResponse
|
||||||
self.alertContact = alertContact
|
self.alertContact = alertContact
|
||||||
|
self.alertName = alertName
|
||||||
|
self.alerted = [False] * len(self.alertThreshold)
|
||||||
|
|
||||||
|
|
||||||
def checkSend(self,value):
|
def checkSend(self,value):
|
||||||
@@ -37,8 +38,8 @@ class DataPoint(object):
|
|||||||
"not": "value != threshold"
|
"not": "value != threshold"
|
||||||
}
|
}
|
||||||
|
|
||||||
for thres,cond in zip(self.alertThreshold,self.alertCondition):
|
"""for thres,cond,name,contact,alerted in zip(self.alertThreshold,self.alertCondition, self.alertName, self.alertContact,self.alerted):
|
||||||
#check value for alert threshold
|
#check value for alert threshold send back first alarmed value
|
||||||
evalVars = {
|
evalVars = {
|
||||||
"value": value,
|
"value": value,
|
||||||
"threshold": thres
|
"threshold": thres
|
||||||
@@ -47,12 +48,32 @@ class DataPoint(object):
|
|||||||
if func == None:
|
if func == None:
|
||||||
print("Not an available function: {}".format(cond))
|
print("Not an available function: {}".format(cond))
|
||||||
else:
|
else:
|
||||||
if eval(func, evalVars):
|
if eval(func, evalVars) and not alerted:
|
||||||
return {"message":"Read value for {} is {} threshold value {}".format(self.name,value,thres)}
|
|
||||||
|
return {"alert": name}
|
||||||
else:
|
else:
|
||||||
self.alerted = False
|
self.alerted = False
|
||||||
return None
|
return None
|
||||||
|
"""
|
||||||
|
for x in range(len(self.alerted)):
|
||||||
|
#check value for alert threshold send back first alarmed value
|
||||||
|
evalVars = {
|
||||||
|
"value": value,
|
||||||
|
"threshold": self.alertThreshold[x]
|
||||||
|
}
|
||||||
|
func = conditions.get(self.alertCondition[x])
|
||||||
|
if func == None:
|
||||||
|
print("Not an available function: {}".format(self.alertCondition[x]))
|
||||||
|
else:
|
||||||
|
result = eval(func,evalVars)
|
||||||
|
if result and not self.alerted[x]:
|
||||||
|
self.alerted[x] = True
|
||||||
|
return {"alert": self.alertName[x], "contact": self.alertContact[x]}
|
||||||
|
elif result and self.alerted[x]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.alerted[x] = False
|
||||||
|
return None
|
||||||
|
|
||||||
class modbusDataPoint(DataPoint):
|
class modbusDataPoint(DataPoint):
|
||||||
def __init__(self,changeThreshold,guaranteed,name,register=1,baud=19200,stopBits=1,parity=None, device='/dev/ttyS0'):
|
def __init__(self,changeThreshold,guaranteed,name,register=1,baud=19200,stopBits=1,parity=None, device='/dev/ttyS0'):
|
||||||
@@ -69,8 +90,8 @@ class modbusDataPoint(DataPoint):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class plcDataPoint(DataPoint):
|
class plcDataPoint(DataPoint):
|
||||||
def __init__(self,changeThreshold,guaranteed,name,plcIP='192.168.1.10',plcType='Micro800',tag=None,alertThreshold=[],alertCondition=[],alertResponse=[],alertContact=[]):
|
def __init__(self,changeThreshold,guaranteed,name,plcIP='192.168.1.10',plcType='Micro800',tag=None,alertThreshold=[],alertCondition=[],alertResponse=[],alertContact=[], alertName=[]):
|
||||||
DataPoint.__init__(self,changeThreshold,guaranteed,name,alertThreshold,alertCondition,alertResponse,alertContact)
|
DataPoint.__init__(self,changeThreshold,guaranteed,name,alertThreshold,alertCondition,alertResponse,alertContact,alertName)
|
||||||
self.plcIP = plcIP
|
self.plcIP = plcIP
|
||||||
self.plcType = plcType
|
self.plcType = plcType
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
|
|||||||
33
driver.py
33
driver.py
@@ -23,7 +23,6 @@ def run(config, device, port, host, rootCAPath):
|
|||||||
console_out.setFormatter(log_formatter)
|
console_out.setFormatter(log_formatter)
|
||||||
filelogger.addHandler(console_out)
|
filelogger.addHandler(console_out)
|
||||||
|
|
||||||
filelogger.info("IN Driver")
|
|
||||||
filelogger.info("Got Config: \n{}".format(config))
|
filelogger.info("Got Config: \n{}".format(config))
|
||||||
|
|
||||||
#Extract data from passed in config
|
#Extract data from passed in config
|
||||||
@@ -75,7 +74,8 @@ def run(config, device, port, host, rootCAPath):
|
|||||||
condition = config['PLCData'][key]["alert"]["condition"]
|
condition = config['PLCData'][key]["alert"]["condition"]
|
||||||
response = config['PLCData'][key]["alert"]["response"]
|
response = config['PLCData'][key]["alert"]["response"]
|
||||||
contact = config['PLCData'][key]["alert"]["contact"]
|
contact = config['PLCData'][key]["alert"]["contact"]
|
||||||
datapoint = plcDataPoint(changeThreshold,guaranteed,str(name),plcIP=str(plcIP),plcType=str(plcType),tag=str(tag),alertThreshold=threshold,alertCondition=condition,alertResponse=response,alertContact=contact)
|
alertName = config['PLCData'][key]["alert"]["name"]
|
||||||
|
datapoint = plcDataPoint(changeThreshold,guaranteed,str(name),plcIP=str(plcIP),plcType=str(plcType),tag=str(tag),alertThreshold=threshold,alertCondition=condition,alertResponse=response,alertContact=contact, alertName=alertName)
|
||||||
else:
|
else:
|
||||||
datapoint = plcDataPoint(changeThreshold,guaranteed,str(name),plcIP=str(plcIP),plcType=str(plcType),tag=str(tag))
|
datapoint = plcDataPoint(changeThreshold,guaranteed,str(name),plcIP=str(plcIP),plcType=str(plcType),tag=str(tag))
|
||||||
datapoints.append(datapoint)
|
datapoints.append(datapoint)
|
||||||
@@ -88,18 +88,18 @@ def run(config, device, port, host, rootCAPath):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
#build alert points
|
#A function for polling data and checking alert status per datapoint.
|
||||||
#A function for polling general data can be latent no greater than a min between polls
|
#Latency should remain low on polls but manage thresholds for how often to send data
|
||||||
#loop through list of data points to read and check value changes
|
#Loop through list of data points to read value, check send thresholds, and check alert thresholds
|
||||||
#sleep for 30 secs
|
|
||||||
def dataCollection():
|
def dataCollection():
|
||||||
while True:
|
while True:
|
||||||
message = {}
|
message = {}
|
||||||
for datapoint in datapoints:
|
for datapoint in datapoints:
|
||||||
val,alertMessage = datapoint.read()
|
val,alertMessage = datapoint.read()
|
||||||
if alertMessage != None and not datapoint.alerted :
|
if alertMessage != None:
|
||||||
|
alertMessage["location"] = locationID
|
||||||
|
filelogger.info("Publishin: {}\nTo Topic: {}".format(alertMessage,alm_topic))
|
||||||
myAWSIoTMQTTClient.publish(alm_topic,json.dumps(alertMessage),1)
|
myAWSIoTMQTTClient.publish(alm_topic,json.dumps(alertMessage),1)
|
||||||
datapoint.alerted =True
|
|
||||||
if datapoint.checkSend(val):
|
if datapoint.checkSend(val):
|
||||||
message[datapoint.name] = val
|
message[datapoint.name] = val
|
||||||
if message:
|
if message:
|
||||||
@@ -108,19 +108,6 @@ def run(config, device, port, host, rootCAPath):
|
|||||||
myAWSIoTMQTTClient.publish(dt_topic, json.dumps(message),1)
|
myAWSIoTMQTTClient.publish(dt_topic, json.dumps(message),1)
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
#A function for polling alert data should be very near real time
|
|
||||||
#if plcdata != to empty then setup polls for tags
|
|
||||||
#use ping and reads as watchdog values for connectivity
|
|
||||||
#if modbusdata != to empty then setup polls for registers
|
|
||||||
#use reads as watchdog values for connectivity
|
|
||||||
#if currentdata != to empty then setup polls for current
|
|
||||||
#if raw current value > 3.5 then current is good else current disconnected
|
|
||||||
#if voltagedata != to empty then setup polls for voltage
|
|
||||||
#if raw voltage value > 0 then voltage is good else voltage disconnected
|
|
||||||
#sleep for 1 secs
|
|
||||||
def alertCollection():
|
|
||||||
pass
|
|
||||||
#Start a thread for data and a thread for alerts
|
|
||||||
|
|
||||||
|
|
||||||
# list of all threads, so that they can be killed afterwards
|
# list of all threads, so that they can be killed afterwards
|
||||||
@@ -130,10 +117,6 @@ def run(config, device, port, host, rootCAPath):
|
|||||||
data_thread.start()
|
data_thread.start()
|
||||||
all_threads.append(data_thread)
|
all_threads.append(data_thread)
|
||||||
|
|
||||||
alert_thread = threading.Thread(target=alertCollection, args=(), name="Thread-alerts")
|
|
||||||
alert_thread.start()
|
|
||||||
all_threads.append(alert_thread)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for thread in all_threads:
|
for thread in all_threads:
|
||||||
|
|||||||
37
utilities.py
37
utilities.py
@@ -1,37 +0,0 @@
|
|||||||
def unmarshal_dynamodb_json(node):
|
|
||||||
data = dict({})
|
|
||||||
data['M'] = node
|
|
||||||
return _unmarshal_value(data)
|
|
||||||
|
|
||||||
|
|
||||||
def _unmarshal_value(node):
|
|
||||||
if type(node) is not dict:
|
|
||||||
return node
|
|
||||||
|
|
||||||
for key, value in node.items():
|
|
||||||
key = key.lower()
|
|
||||||
if key == 'bool':
|
|
||||||
return value
|
|
||||||
if key == 'null':
|
|
||||||
return None
|
|
||||||
if key == 's':
|
|
||||||
return value
|
|
||||||
if key == 'n':
|
|
||||||
if '.' in str(value):
|
|
||||||
return float(value)
|
|
||||||
return int(value)
|
|
||||||
if key in ['m', 'l']:
|
|
||||||
if key == 'm':
|
|
||||||
data = {}
|
|
||||||
for key1, value1 in value.items():
|
|
||||||
if key1.lower() == 'l':
|
|
||||||
data = [_unmarshal_value(n) for n in value1]
|
|
||||||
else:
|
|
||||||
if type(value1) is not dict:
|
|
||||||
return _unmarshal_value(value)
|
|
||||||
data[key1] = _unmarshal_value(value1)
|
|
||||||
return data
|
|
||||||
data = []
|
|
||||||
for item in value:
|
|
||||||
data.append(_unmarshal_value(item))
|
|
||||||
return data
|
|
||||||
Reference in New Issue
Block a user