#!/usr/bin/env python2.6 #-*- coding: utf-8 -*- __author__ = "Michael Rest" __date__ = "1 August 2010" __email__ = "michi@rosstein.de" __version__ = "$Revision: 1.0 $"[11:-2] import os from log import log import sys from datetime import date, datetime, timedelta from select import select from time import time, strptime from ConfigParser import * from SOAPpy import SOAPProxy, SOAPServer from redis import Redis from pydave import pydave from davedefs import * from DB import DB pid_file= '/tmp/ipserv.lock' class IOSERV (object): def __init__ (self, loglevel = 6, logfile = "/tmp/log_ioserv.txt", db = "test.db3"): self.server = None self.rproxy = None self.DB = DB (db) self.loglevel = int (loglevel) self.logfile = logfile self.conns = {} def __del__ (self): for cname in conns: conns [cname].DisconnectPLC () def log (self, msg, level): """ Print message if in verbose mode. """ if level >= self.loglevel: file = open (self.logfile, "a") dt = datetime.now () file.write ("%4d-%02d-%02d %02d:%02d:%02d.%06d: " %(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond)), file.write (msg + "\n") file.close () def SOAPserver (self, host = 'localhost', port = 8081): self.server = SOAPServer ((host, port)) self.server.registerFunction (self.setQuit) self.server.registerFunction (self.setMaintenance) self.server.registerFunction (self.setDone) self.log ("SOAP Server created", 6) def RedisProxy (self, rserv): self.rproxy = Redis (rserv) self.log ("Redis Client created", 6) def adddaveconn (self, name, proto, addr, port, mpi, rack, slot, rsid1, rsid2, rrack, rslot, rmpi): #routingSubnetFirst, routingSubnetSecond, routingRack, routingSlot if not proto in ["ISO_TCP", "IBH_Link"]: self.log ("Bad Protocol for DaveConn", 1) sys.exit (1) if name in self.conns: self.log ("Connection already exits", 1) self.conns [name] = pydave () self.conns [name].OpenSocket (proto, addr, port, mpi, rack, slot, rsid1, rsid2, rrack, rslot, rmpi) def logtext (self, txt = "test"): dt = datetime.now () timestamp = "%4d-%02d-%02d %02d:%02d:%02d.%06d: " %(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) self.builder.get_object ("textbuffer1").set_text (timestamp + txt) def simulation (self): Dummyvar = 0 def setQuit (self, cname, msgnr): """ SOAP RPC Funciton - Set Errormsg Quit-Bit """ if msgnr not in range (2000, 2500): self.log ("Bad MsgNr for Quit", 1) return -1 byteaddr = 2000 + (msgnr - 2000) / 8 bitaddr = (msgnr - 2000) % 8 self.log ("Set Quit for MsgNr %s Adr %s.%s" % (msgnr, byteaddr, bitaddr), 6) self.conns [cname].SetBit (daveAreas["DB"], 2, byteaddr, bitaddr) self.rcvErrorstates (cname, msgnr) def setMaintenance (self, cname, msgnr): """ SOAP RPC Funciton - Set Errormsg on Maintenance """ if msgnr not in range (2000, 2500): self.log ("Bad MsgNr for Maintenance", 1) return -1 byteaddr = 2064 + (msgnr - 2000) / 8 bitaddr = (msgnr - 2000) % 8 self.log ("Set Maintenance for MsgNr %s Adr %s.%s" % (msgnr, byteaddr, bitaddr), 6) self.conns [cname].SetBit (daveAreas["DB"], 2, byteaddr, bitaddr) self.rcvErrorstates (cname, msgnr) def setDone (self, cname, msgnr): """ SOAP RPC Funciton - Set Errormsg Done """ if msgnr not in range (2000, 2500): self.log ("Bad MsgNr for Done", 1) return -1 byteaddr = 2128 + (msgnr - 2000) / 8 bitaddr = (msgnr - 2000) % 8 self.log ("Set Maintenance for MsgNr %s Adr %s.%s" % (msgnr, byteaddr, bitaddr), 6) self.conns [cname].SetBit (daveAreas["DB"], 2, byteaddr, bitaddr) self.rcvErrorstates (cname, msgnr) def setControl (self, cname, ctrlnr): if ctrlnr not in range (16): self.log ("Bad MsgNr for Ctrl", 1) return -1 byteaddr = ctrlnr / 8 bitaddr = ctrlnr % 8 self.log ("Set Ctrl for Conn %s CtrlNr %s cwAdr %s.%s" % (cname, msgnr, byteaddr, bitaddr), 6) self.conns [cname].SetBit (daveAreas["DB"], 5, byteaddr, bitaddr) def rcvErrorstates (self, cname, msgnr = 0): if msgnr in range (2000, 2500): nr = msgnr - 1999 limit = msgnr - 1999 offset = (msgnr - 2000) * 4 blocksize = 4 else: nr = 1 limit = 299 offset = 0 blocksize = 220 ttl = 60 r_pipe = self.rproxy.pipeline () while nr <= limit: val = self.conns [cname].ReadBytes (daveAreas["DB"], 2, offset, blocksize) for i in range (len (val) / 4): counter = (val [i * 4 + 0] << 8) + val [i * 4 + 1] self.log ("%s Counter = %d" % (nr, counter), 6) self.log ("%s State = %d" % (nr, val [i * 4 + 2]), 6) self.log ("%s Action = %d" % (nr, val [i * 4 + 3]), 6) r_pipe.setex('Counter%03d' % nr, counter, ttl) r_pipe.setex('State%03d' % nr, val [i * 4 + 2], ttl) r_pipe.setex('Action%03d' % nr, val [i * 4 + 3], ttl) nr += 1 offset += blocksize r_pipe.execute () def rcvVisuState (self, cname): ttl = 60 if cname in ['HALLEA','HALLEB']: dbnr = 3 blocksize = 8 else: dbnr = 6 blocksize = 2 offset = 0 val = self.conns [cname].ReadBytes (daveAreas["DB"], dbnr, offset, blocksize) r_pipe = self.rproxy.pipeline () for i in range (blocksize / 2): state = (val [i * 2 + 0] << 8) + val [i * 2 + 1] self.log ("%s-Visu%02d = %d" % (cname, i, state), 6) r_pipe.setex('%s-Visu%02d' % (cname, i) , state, ttl) r_pipe.execute () def rcvCamState (self, cname): ttl = 60 offset = 5 blocksize = 2 val = self.conns [cname].ReadBytes (daveAreas["DB"], 3, offset, blocksize) state = (val [0] << 8) + val [1] self.log ("%s-Cams = %d" % (cname, state), 6) r_pipe = self.rproxy.pipeline () r_pipe.setex('%s-Cams' % cname, state, ttl) r_pipe.execute () def rcvErrorlogs (self, cname = 'ABP-Buero'): val = self.conns [cname].ReadBytes (daveAreas["DB"], 104, 0, 16) if int (val [1]): mid = (val [2] << 8) + val [3] year = val [4] month = val [5] day = val [6] hour = val [7] minute = val [8] seconds = val [9] cnt = (val [12] << 8) + val [13] stat = val [14] act = val [15] ts = "20%02x-%02x-%02x %02x:%02x:%02x" % (year, month, day, hour, minute, seconds) self.log ("New Errorlog ID:%s Count:%s State:%s Act:%s %s" % (mid, cnt, stat, act, ts), 6) self.DB.logmsg (ts, mid + 1999, cnt, act) val = self.conns [cname].WriteBytes (daveAreas["DB"], 104, 1, 1, '0') if __name__ == '__main__': #Double fork to daemonize from os import fork, setsid, umask, dup2 from sys import stdin, stdout, stderr from os import getpid simulation = 0 if '--simulate' in sys.argv: simulation = 1 if os.path.isfile (pid_file): pidfile = open (pid_file, 'r') pid = pidfile.read () _r = 0 try: #Already running os.kill (int (pid), 0) _r = 1 except: #No Process on this PID os.remove (pid_file) if _r: sys.exit (0) pidfile = open (pid_file, 'w') pidfile.write('%i' % getpid()) pidfile.close() log ("========================================================================================") log ("ioserv.py started") config = ConfigParser () config.read ('ioserv.cfg') uid = config.get ('PARAM', 'id') if not uid: print ("Ioserv ID not defined") raise Warning loglevel = config.get ('DEBUG', 'loglevel') logfile = config.get ('DEBUG', 'logfile') #Instace app = IOSERV (loglevel = loglevel, logfile = logfile) if simulation: app.simulation () #Create SOAPServer host = config.get ('SOAP', 'host') if host: app.SOAPserver (host, 8089) #Create Redis Proxy rserv = config.get ('REDIS', 'host') if rserv: app.RedisProxy (rserv) #_name, _proto, _addr, _port, _mpi, _rack, _slot, _rsid1, _rsid2, _rrack, _rslot, _rmpi # MPI Adress 2 app.adddaveconn ('HALLEA', 'IBH_Link', '192.168.11.99', 1099, 2, 0, 4, 0, 0, 0, 0, 0) # MPI Adress 3 app.adddaveconn ('HALLEB', 'IBH_Link', '192.168.11.99', 1099, 3, 0, 4, 0, 0, 0, 0, 0) # MPI Adress 4 app.adddaveconn ('ABP-Buero', 'IBH_Link', '192.168.11.99', 1099, 4, 0, 4, 0, 0, 0, 0, 0) lastcycle = 0 #Mainloop while 1: #prepare select writecons= [] sockets = [] #SOAP Server if app.server: sockets.append ([app.server.fileno ()]) writes = [i[0] for i in writecons] (reads, writes, xlist) = select ([i[0] for i in sockets], writes, [], 0.1) readcons = [i for i in sockets if i[0] in reads] writecons = [i for i in writecons if i[0] in writes] for conn, data, client_id, tpye in writecons: log ("Found a write telegram", 6) ## Serial Connection , sockets have other methods while 1: _l = os.write (conn, data) log ("..os.wrote %d bytes" %_l, 6) log ("..os.wrote data: %s" %strlog (data), 6) break for conn in readcons: log ('Got Input', 6) if app.server and conn[0] == app.server.fileno (): log ("Got request on SOAP Server", 6) app.server.handle_request () nt = time () app.log ("Retrieve Logs", 6) app.rcvErrorlogs () if nt - lastcycle > 5: app.log ("<<>> Errorstates", 6) app.rcvErrorstates ('ABP-Buero') app.log ("<<>> Camstates", 6) app.rcvCamState ('HALLEA') app.rcvCamState ('HALLEB') app.log ("<<>> Visustates", 6) app.rcvVisuState ('HALLEA') app.rcvVisuState ('HALLEB') app.rcvVisuState ('ABP-Buero') lastcycle = nt