329 lines
9.5 KiB
Python
Executable File
329 lines
9.5 KiB
Python
Executable File
#!/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
|
|
|
|
|
|
|