Files
ioserv/ioserv.py
2015-08-24 19:42:38 +02:00

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