From 48689f7ed87ee17853f1f3733afed27f3532e56b Mon Sep 17 00:00:00 2001 From: Patrick McDonagh Date: Wed, 13 Jan 2016 10:02:05 -0600 Subject: [PATCH] Initial Commit --- python/solar_ww.py | 67 +++++++++ python/tuxeip.py | 276 ++++++++++++++++++++++++++++++++++++ python/tuxeip.pyc | Bin 0 -> 9827 bytes www/app.js | 78 ++++++++++ www/dbcreate.sql | 15 ++ www/functions.js | 68 +++++++++ www/package.json | 25 ++++ www/views/angularIndex.html | 66 +++++++++ 8 files changed, 595 insertions(+) create mode 100644 python/solar_ww.py create mode 100644 python/tuxeip.py create mode 100644 python/tuxeip.pyc create mode 100644 www/app.js create mode 100644 www/dbcreate.sql create mode 100644 www/functions.js create mode 100644 www/package.json create mode 100644 www/views/angularIndex.html diff --git a/python/solar_ww.py b/python/solar_ww.py new file mode 100644 index 0000000..b811260 --- /dev/null +++ b/python/solar_ww.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +''' +Created on Dec 8, 2015 + +@author: Patrick McDonagh +''' + + +from datetime import datetime +import sys +from random import randint +import time +import MySQLdb +import tuxeip + + +#TUXEIP Connection to PLC +from tuxeip import TuxEIP, LGX, LGX_REAL + + +def main(): + + db = MySQLdb.connect(host="127.0.0.1",user="website",passwd="henrypump",db="SolarData") + cur = db.cursor() + query = "SELECT * FROM SolarData.tags WHERE deleted = 0;" + cur.execute(query) + tags = cur.fetchall() + # ((1L, 'DC_Bus_Voltage', datetime.datetime(2015, 12, 8, 16, 2, 32), 'V', 0L), (2L, 'Output_Frequency', datetime.datetime(2015, 12, 8, 16, 31, 12), 'Hz', 0L)) + db.commit() + db.close() + + PLC_IP_ADDRESS = "192.168.1.13" # MAKE THIS A db VALUE + + tagList = []; + if len(tags) > 0: + for t in tags: + tagList.append({"id":int(t[0]), "name":t[1], "val":None, "lastVal":None}); + + try: + tux = TuxEIP(libpath="/usr/lib/libtuxeip.so") + sess = tux.OpenSession(PLC_IP_ADDRESS) + reg = tux.RegisterSession(sess) + conn = tux.ConnectPLCOverCNET(sess, LGX, 1, 100, 123, randint(0,9999), 123, 321, 100, 5000, 1, '01') + + while True: + for r in tagList: + r["val"] = tux.ReadLGXDataAsFloat(sess, conn, r['name'], 1)[0] + print("{0} - {1}".format(r["name"], r["val"])) + if not r["val"] == r["lastVal"]: + db = MySQLdb.connect(host="127.0.0.1",user="website",passwd="henrypump",db="SolarData") + cur = db.cursor() + aQuery = """INSERT INTO SolarData.values (tagID, val) VALUES ('%d', '%f');"""%(r["id"], float(r["val"])) + print(aQuery) + storeVal = cur.execute(aQuery) + db.commit() + db.close() + r["lastVal"] = r["val"] + + time.sleep(10) + except Exception as err: + print err + pass + + +if __name__ == '__main__': + main() diff --git a/python/tuxeip.py b/python/tuxeip.py new file mode 100644 index 0000000..1c39e40 --- /dev/null +++ b/python/tuxeip.py @@ -0,0 +1,276 @@ +#! /usr/bin/env python + +# Copyright (C) 2014 Gayner Technical Services Pty Ltd + +from ctypes import * + +# PLC TYPES +Unknow=0 +PLC=1 +SLC500=2 +LGX=3 + +# EIP DATA TYPES +PLC_BIT=1 +PLC_BIT_STRING=2 +PLC_BYTE_STRING=3 +PLC_INTEGER=4 +PLC_TIMER=5 +PLC_COUNTER=6 +PLC_CONTROL=7 +PLC_FLOATING=8 +PLC_ARRAY=9 +PLC_ADRESS=15 +PLC_BCD=16 + +# LOGIX DATA TYPES +LGX_BOOL=0xC1 +LGX_BITARRAY=0xD3 +LGX_SINT=0xC2 +LGX_INT=0xC3 +LGX_DINT=0xC4 +LGX_REAL=0xCA + +class Eip_Session(Structure): + _fields_ = [ + ('sock',c_int), + ('Session_Handle', c_uint), + ('Sender_ContextL',c_int), + ('Sender_ContextH',c_int), + ('timeout', c_int), + ('references', c_int), + ('Data', c_void_p), + ] + +class Eip_Connection(Structure): + _fields_ = [ + ('Eip_Session', Eip_Session), + ('references', c_int), + ('Data', c_void_p), + ('ConnectionSerialNumber', c_uint), + ('OriginatorVendorID', c_uint), + ('OriginatorSerialNumber', c_int), + ('OT_ConnID', c_int), + ('TO_ConnID', c_int), + ('packet', c_short), + ('Path_size', c_byte) + ] + +class Eip_PLC_Read(Structure): + _fields_ = [ + ('type', c_int), + ('Varcount', c_int), + ('totalise', c_int), + ('elementsize', c_int), + ('mask', c_uint), + ] + +class TuxEIPException(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + +class TuxEIP: + + def __init__(self, **kwargs): + self.__libpath = kwargs.get("libpath", "libtuxeip.dylib") + self.__tuxeip = CDLL(self.__libpath) + self.__tuxeip._cip_err_msg.restype = c_char_p + + def __del__(self): + del self.__tuxeip + + def OpenSession(self, slaveip_, slaveport_=44818, slavetimeout_=1000): + self.__tuxeip._OpenSession.restype = POINTER(Eip_Session) + + # Convert params to C types + slaveip = c_char_p(slaveip_) + slaveport = c_int(slaveport_) + slavetimeout = c_int(slavetimeout_) + + session = self.__tuxeip._OpenSession(slaveip, slaveport, slavetimeout) + + #print self.__tuxeip._cip_err_msg, self.__tuxeip._cip_errno, self.__tuxeip._cip_ext_errno + + if bool(session) == False: + raise TuxEIPException("Could not open session to " + str(slaveip) + ":" + str(slaveport)) + + return session + + def RegisterSession(self, sess_): + self.__tuxeip._RegisterSession.restype = c_int + reg = self.__tuxeip._RegisterSession(sess_) + + if reg != False: + raise TuxEIPException("Could not register session") + + return reg + + def ConnectPLCOverCNET(self, sess_, plctype_, priority_, timeoutticks_, connid_, conserial_, + vendorid_, serialnum_, timeoutmult_, rpi_, transport_, slavepath_): + # Convert params to C types + priority = c_byte(priority_) + timeoutticks = c_byte(timeoutticks_) + connid = c_uint(connid_) + conserial = c_ushort(conserial_) + vendorid = c_ushort(vendorid_) + serialnum = c_uint(serialnum_) + timeutmult = c_byte(timeoutmult_) + rpi = c_uint(rpi_) + transport = c_byte(transport_) + slavepath = c_char_p(slavepath_) + pathlength = len(slavepath_) + + self.__tuxeip._ConnectPLCOverCNET.restype = POINTER(Eip_Connection) + + connection = self.__tuxeip._ConnectPLCOverCNET( + sess_, + plctype_, + priority, + timeoutticks, + connid, + conserial, + vendorid, + serialnum, + timeutmult, + rpi, + transport, + slavepath, + pathlength + ) + + if bool(connection) == False: + raise TuxEIPException("Could not connect to CPU") + + return connection + + def ReadLgxData(self, sess_, conn_, var_, num_): + self.__tuxeip._ReadLgxData.restype = POINTER(Eip_PLC_Read) + readdata = self.__tuxeip._ReadLgxData(sess_, conn_, var_, num_) + + if bool(readdata) == False: + raise TuxEIPException("Read data failed") + + return readdata + + def WriteLGXData(self, sess_, conn_, address_, datatype_, data_, num_ ): + if datatype_ == LGX_INT or datatype_ == LGX_BOOL or datatype_ == LGX_DINT or datatype_ == LGX_SINT: + data = c_int(data_) + elif datatype_ == LGX_REAL: + data = c_float(data_) + else: + raise TuxEIPException("Write data failed") + + data = self.__tuxeip._WriteLgxData(sess_, conn_, address_, datatype_, byref(data), num_) + + return data + + def ReadLGXDataAsFloat(self, sess_, conn_, var_, num_): + data = self.ReadLgxData(sess_, conn_, var_, num_) + d = self.GetLGXValueAsFloat(data) + self.FreePLCRead(data) + return d + + def ReadLGXDataAsInteger(self, sess_, conn_, var_, num_): + data = self.ReadLgxData(sess_, conn_, var_, num_) + d = self.GetLGXValueAsInteger(data) + self.FreePLCRead(data) + return d + + def ReadPLCDataAsFloat(self, sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, number_): + data = self.ReadPLCData(sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, number_) + d = self.PCCC_GetValueAsFloat(data) + self.FreePLCRead(data) + return d + + def ReadPLCDataAsInteger(self, sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, number_): + data = self.ReadPLCData(sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, number_) + d = self.PCCC_GetValueAsInteger(data) + self.FreePLCRead(data) + return d + + def ReadPLCData(self, sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, number_): + self.__tuxeip._ReadPLCData.restype = POINTER(Eip_PLC_Read) + readdata = self.__tuxeip._ReadPLCData(sess_, conn_, dhp_, routepath_, routesize_, plctype_, + tns_, address_, number_) + + if bool(readdata) == False: + raise TuxEIPException("Read data failed") + + return readdata + + def GetLGXValueAsFloat(self, readdata_): + if bool(readdata_) == False: + return None + + self.__tuxeip._GetLGXValueAsFloat.restype = c_float + values = [] + for i in range(0, readdata_.contents.Varcount): + v = self.__tuxeip._GetLGXValueAsFloat(readdata_, i) + values.append(v) + + return values + + def GetLGXValueAsInteger(self, readdata_): + if bool(readdata_) == False: + return None + + self.__tuxeip._GetLGXValueAsInteger.restype = c_int + values = [] + for i in range(0, readdata_.contents.Varcount): + v = self.__tuxeip._GetLGXValueAsInteger(readdata_, i) + values.append(v) + + return values + + def PCCC_GetValueAsFloat(self, readdata_): + if bool(readdata_) == False: + return None + + self.__tuxeip._PCCC_GetValueAsFloat.restype = c_float + values = [] + for i in range(0, readdata_.contents.Varcount): + v = self.__tuxeip._PCCC_GetValueAsFloat(readdata_, i) + values.append(v) + + return values + + def PCCC_GetValueAsInteger(self, readdata_): + if bool(readdata_) == False: + return None + + self.__tuxeip._PCCC_GetValueAsInteger.restype = c_int + values = [] + for i in range(0, readdata_.contents.Varcount): + v = self.__tuxeip._PCCC_GetValueAsInteger(readdata_, i) + values.append(v) + + return values + + def WritePLCData(self, sess_, conn_, dhp_, routepath_, routesize_, plctype_, tns_, address_, datatype_, data_, number_): + + if datatype_ == PLC_INTEGER: + data = c_int(data_) + elif datatype_ == PLC_FLOATING: + data = c_float(data_) + else: + raise TuxEIPException("Variable type not supported" + str(datatype_)) + + result = self.__tuxeip._WritePLCData(sess_, conn_, dhp_, routepath_, routesize_, plctype_, + tns_, address_, datatype_, byref(data), number_) + + return result + + def Forward_Close(self, conn_): + self.__tuxeip._Forward_Close(conn_) + + def UnRegisterSession(self, sess_): + self.__tuxeip._UnRegisterSession(sess_) + + def CloseSession(self, sess_): + self.__tuxeip.CloseSession(sess_) + + def FreePLCRead(self, data_): + self.__tuxeip._FreePLCRead(data_) diff --git a/python/tuxeip.pyc b/python/tuxeip.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92f884853e1d06ffb6c2200c43557714fc6cf1f2 GIT binary patch literal 9827 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 + + + POConsole: {{ Page.title() }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+