Initial commit

This commit is contained in:
2020-01-28 14:59:07 -06:00
commit 3bb2fdfad6
108 changed files with 24266 additions and 0 deletions

143
driver.py Normal file
View File

@@ -0,0 +1,143 @@
import json
import time
from datetime import datetime as datetime
import logging
from logging.handlers import RotatingFileHandler
import sys
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import threading
from data_points import plcDataPoint,modbusDataPoint,currentDataPoint,voltageDataPoint
def run(config, device, port, host, rootCAPath):
log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')
log_file = './logs/{}.log'.format(device)
my_handler = RotatingFileHandler(log_file, mode='a', maxBytes=500*1024, backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)
filelogger = logging.getLogger('{}'.format(device))
filelogger.setLevel(logging.INFO)
filelogger.addHandler(my_handler)
console_out = logging.StreamHandler(sys.stdout)
console_out.setFormatter(log_formatter)
filelogger.addHandler(console_out)
filelogger.info("IN Driver")
filelogger.info("Got Config: \n{}".format(config))
#Extract data from passed in config
app = config['appname']
company = config['company']
field = config['field']
locationID = config['locationID']
#deviceType = config['deviceType']
certificateID = config['certificateID']
#Build a topic and last will payload
dt_topic = "dt/{}/{}/{}/{}".format(app, company, field, locationID)
alm_topic = "alm/{}/{}/{}/{}".format(app,company, field, locationID)
lwtPayload = {"connected": 0}
#Generate a cert if needed
#Configure connection to AWS IoT Core with proper certificate
myAWSIoTMQTTClient = None
myAWSIoTMQTTClient = AWSIoTMQTTClient(certificateID)
myAWSIoTMQTTClient.configureEndpoint(host, port)
myAWSIoTMQTTClient.configureCredentials(rootCAPath, './device1Cert.key', './device1CertAndCACert.pem')
myAWSIoTMQTTClient.configureLastWill(dt_topic,json.dumps(lwtPayload),1)
try:
myAWSIoTMQTTClient.connect()
connectedPayload = {"connected": 1}
myAWSIoTMQTTClient.publish(dt_topic, json.dumps(connectedPayload),1)
except Exception as e:
filelogger.info("Didn't connect: {}".format(e))
#build data points loop through config and use a class to make a data point
#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
datapoints = []
if not config["PLCData"] == "empty":
for key in config['PLCData'].keys():
changeThreshold = config['PLCData'][key]["changeThreshold"]
guaranteed = config['PLCData'][key]["guaranteed"]
plcIP = config['PLCData'][key]["plcIP"]
plcType = config['PLCData'][key]["plcType"]
tag = config['PLCData'][key]["tag"]
name = config['PLCData'][key]["name"]
if "alert" in config['PLCData'][key].keys():
threshold = config['PLCData'][key]["alert"]["threshold"]
condition = config['PLCData'][key]["alert"]["condition"]
response = config['PLCData'][key]["alert"]["response"]
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)
else:
datapoint = plcDataPoint(changeThreshold,guaranteed,str(name),plcIP=str(plcIP),plcType=str(plcType),tag=str(tag))
datapoints.append(datapoint)
if not config["modbusData"] == "empty":
pass
if not config["currentData"] == "empty":
pass
if not config["voltageData"] == "empty":
pass
#build alert points
#A function for polling general data can be latent no greater than a min between polls
#loop through list of data points to read and check value changes
#sleep for 30 secs
def dataCollection():
while True:
message = {}
for datapoint in datapoints:
val,alertMessage = datapoint.read()
if alertMessage != None and not datapoint.alerted :
myAWSIoTMQTTClient.publish(alm_topic,json.dumps(alertMessage),1)
datapoint.alerted =True
if datapoint.checkSend(val):
message[datapoint.name] = val
if message:
message["timestamp"] = datetime.now().isoformat()
filelogger.info("Publishing: {}\nTo Topic: {}".format(message,dt_topic))
myAWSIoTMQTTClient.publish(dt_topic, json.dumps(message),1)
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
all_threads = []
data_thread = threading.Thread(target=dataCollection, args=(), name="Thread-data")
data_thread.start()
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:
thread.join()
#myAWSIoTMQTTClient.disconnect()