X-Git-Url: https://git.realraum.at/?p=svn42.git;a=blobdiff_plain;f=update-web-status.py;h=e1e24126eb068e6da95cf45d5a765569b7423388;hp=8aa58e13456960eec08465f1509667e09260a88b;hb=9b57ad36fa772a94f8f38321a88f2b1df1818a51;hpb=2f2fa1baaf28c4cf64a3dd393579559e9dd63e45 diff --git a/update-web-status.py b/update-web-status.py index 8aa58e1..e1e2412 100755 --- a/update-web-status.py +++ b/update-web-status.py @@ -5,6 +5,7 @@ import os.path import sys #import threading import logging +import logging.handlers import urllib import time import signal @@ -14,27 +15,29 @@ import subprocess import types import ConfigParser -#logging.basicConfig(level=logging.INFO,filename='/var/log/tmp/tuer.log',format="%(asctime)s %(message)s",datefmt="%Y-%m-%d %H:%M") -logging.basicConfig( - level=logging.ERROR, - #level=logging.DEBUG, - format="%(asctime)s %(message)s", - datefmt="%Y-%m-%d %H:%M" - ) +logger = logging.getLogger() +logger.setLevel(logging.INFO) +lh_syslog = logging.handlers.SysLogHandler(address="/dev/log",facility=logging.handlers.SysLogHandler.LOG_LOCAL2) +lh_syslog.setFormatter(logging.Formatter('update-web-status.py: %(levelname)s %(message)s')) +logger.addHandler(lh_syslog) +lh_stderr = logging.StreamHandler() +logger.addHandler(lh_stderr) class UWSConfig: def __init__(self,configfile=None): self.configfile=configfile self.config_parser=ConfigParser.ConfigParser() - self.config_parser.add_section('url') - self.config_parser.set('url','open','https://www.realraum.at/cgi/status.cgi?pass=jako16&set=%3Chtml%3E%3Cbody%20bgcolor=%22lime%22%3E%3Ccenter%3E%3Cb%3ET%26uuml%3Br%20ist%20Offen%3C/b%3E%3C/center%3E%3C/body%3E%3C/html%3E') - self.config_parser.set('url','closed','https://www.realraum.at/cgi/status.cgi?pass=jako16&set=%3Chtml%3E%3Cbody%20bgcolor=%22red%22%3E%3Cb%3E%3Ccenter%3ET%26uuml%3Br%20ist%20Geschlossen%3C/center%3E%3C/b%3E%3C/body%3E%3C/html%3E') - self.config_parser.add_section('xmpp') - self.config_parser.set('xmpp','recipients_debug','xro@jabber.tittelbach.at') - self.config_parser.set('xmpp','recipients_normal','xro@jabber.tittelbach.at otti@wirdorange.org') - self.config_parser.set('xmpp','recipients_nooffline','the-equinox@jabber.org') - self.config_parser.set('xmpp','msg_opened',"Realraum Tür wurde%s geöffnet") - self.config_parser.set('xmpp','msg_closed',"Realraum Tür wurde%s geschlossen") + self.config_parser.add_section('web') + self.config_parser.set('web','cgiuri','https://www.realraum.at/cgi/status.cgi?pass=jako16&set=') + #~ self.config_parser.set('web','htmlopen','
Tür ist Offen
') + #~ self.config_parser.set('web','htmlclosed','
Tür ist Geschlossen
') + self.config_parser.set('web','htmlbored','
Panic! Present&Bored
') + self.config_parser.set('web','htmlopen','
Leute Anwesend
') + self.config_parser.set('web','htmlclosed','
Keiner Da
') + self.config_parser.add_section('debug') + self.config_parser.set('debug','enabled',"False") + self.config_parser.add_section('tracker') + self.config_parser.set('tracker','socket',"/var/run/tuer/presence.socket") self.config_mtime=0 if not self.configfile is None: try: @@ -46,20 +49,25 @@ class UWSConfig: self.checkConfigUpdates() def checkConfigUpdates(self): + global logger if self.configfile is None: return logging.debug("Checking Configfile mtime: "+self.configfile) try: mtime = os.path.getmtime(self.configfile) - except IOError: + except (IOError,OSError): return if self.config_mtime < mtime: logging.debug("Reading Configfile") try: self.config_parser.read(self.configfile) self.config_mtime=os.path.getmtime(self.configfile) - except ConfigParser.ParsingError, pe_ex: + except (ConfigParser.ParsingError, IOError), pe_ex: logging.error("Error parsing Configfile: "+str(pe_ex)) + if self.config_parser.get('debug','enabled') == "True": + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.INFO) def writeConfigFile(self): if self.configfile is None: @@ -83,71 +91,87 @@ class UWSConfig: except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): raise AttributeError - - -xmpp_msg_lastmsg = "" -action_by = "" -xmpp_firstmsg = True - -def sendXmppMsg(recipients, msg, resource = "torwaechter", addtimestamp = True, noofflinemsg = False): - if type(recipients) == types.ListType: - recipients = " ".join(recipients) - if type(recipients) == types.UnicodeType: - recipients = recipients.decode("utf-8") - if type(recipients) != types.StringType: - raise Exception("list of recipients in unknown format, can't send message") - if recipients == "" or msg == "": - return - - sendxmpp_cmd = "sendxmpp -u realrauminfo -p 5SPjTdub -j jabber.tittelbach.at -t " - if resource: - sendxmpp_cmd += "-r %s " % resource - if noofflinemsg: - sendxmpp_cmd += "--headline " - sendxmpp_cmd += recipients - - if addtimestamp: - msg += time.strftime(" (%Y-%m-%d %T)") +def popenTimeout1(cmd, pinput, returncode_ok=[0], ptimeout = 20.0, pcheckint = 0.25): + logging.debug("popenTimeout1: starting: " + cmd) + try: + sppoo = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=True) + sppoo.communicate(input=pinput) + timeout_counter=ptimeout + while timeout_counter > 0: + time.sleep(pcheckint) + timeout_counter -= pcheckint + if not sppoo.poll() is None: + logging.debug("popenTimeout2: subprocess %d finished, returncode: %d" % (sppoo.pid,sppoo.returncode)) + return (sppoo.returncode in returncode_ok) + #timeout reached + logging.error("popenTimeout1: subprocess took too long (>%fs), sending SIGTERM to pid %d" % (ptimeout,sppoo.pid)) + if sys.hexversion >= 0x020600F0: + sppoo.terminate() + else: + subprocess.call(["kill",str(sppoo.pid)]) + time.sleep(1.0) + if sppoo.poll() is None: + logging.error("popenTimeout1: subprocess still alive, sending SIGKILL to pid %d" % (sppoo.pid)) + if sys.hexversion >= 0x020600F0: + sppoo.kill() + else: + subprocess.call(["kill","-9",str(sppoo.pid)]) + return False + except Exception, e: + logging.error("popenTimeout1: "+str(e)) + return False - logging.debug("Starting " + sendxmpp_cmd) +def popenTimeout2(cmd, pinput, returncode_ok=[0], ptimeout=21): + logging.debug("popenTimeout2: starting: " + cmd) try: - sppoo = subprocess.Popen(sendxmpp_cmd, stdin=subprocess.PIPE, shell=True) - sppoo.communicate(input=msg) + sppoo = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=True) + if sys.hexversion >= 0x020600F0: + old_shandler = signal.signal(signal.SIGALRM,lambda sn,sf: sppoo.kill()) + else: + old_shandler = signal.signal(signal.SIGALRM,lambda sn,sf: os.system("kill -9 %d" % sppoo.pid)) + signal.alarm(ptimeout) #schedule alarm + sppoo.communicate(input=pinput) sppoo.wait() + signal.alarm(0) #disable pending alarms + signal.signal(signal.SIGALRM, old_shandler) + logging.debug("popenTimeout2: subprocess %d finished, returncode: %d" % (sppoo.pid,sppoo.returncode)) + if sppoo.returncode < 0: + logging.error("popenTimeout2: subprocess took too long (>%ds) and pid %d was killed" % (ptimeout,sppoo.pid)) + return (sppoo.returncode in returncode_ok) except Exception, e: - logging.error(str(e)) - logging.debug("XMPPmessage sent: '%s'" % msg) - -def distributeXmppMsg(msg,high_priority=False): - global xmpp_firstmsg, xmpp_msg_lastmsg - if xmpp_firstmsg: - xmpp_msg_lastmsg = msg - xmpp_firstmsg = False - if msg != xmpp_msg_lastmsg: - sendXmppMsg(uwscfg.xmpp_recipients_normal, msg) - sendXmppMsg(uwscfg.xmpp_recipients_nooffline, msg, noofflinemsg=(not high_priority)) - else: - sendXmppMsg(uwscfg.xmpp_recipients_debug, "D: " + msg) - xmpp_msg_lastmsg = msg - + logging.error("popenTimeout2: "+str(e)) + try: + signal.signal(signal.SIGALRM, old_shandler) + except: + pass + return False + def touchURL(url): try: f = urllib.urlopen(url) - f.read() + rq_response = f.read() + logging.debug("touchURL: Response "+rq_response) f.close() + return rq_response except Exception, e: - logging.error(str(e)) + logging.error("touchURL: "+str(e)) + +def setRealraumHtmlStatus(htmlcode): + htmlcode_escaped = re.sub(r'[^\x30-\x39\x41-\x7E]',lambda m:"%%%x"%ord(m.group(0)),htmlcode) + if touchURL(uwscfg.web_cgiuri + htmlcode_escaped) != htmlcode: + logging.error("setRealraumHtmlStatus: Error setting Status, Output does not match Input") def displayOpen(): - touchURL(uwscfg.url_open) - distributeXmppMsg(uwscfg.xmpp_msg_opened % action_by) + setRealraumHtmlStatus(uwscfg.web_htmlopen) def displayClosed(): - touchURL(uwscfg.url_closed) - distributeXmppMsg(uwscfg.xmpp_msg_closed % action_by) - + setRealraumHtmlStatus(uwscfg.web_htmlclosed) + +def displayPanic(): + setRealraumHtmlStatus(uwscfg.web_htmlbored) + def exitHandler(signum, frame): - logging.info("Door Status Listener stopping") + logging.info("Update-Web-Status stopping") try: conn.close() except: @@ -166,62 +190,76 @@ signal.signal(signal.SIGQUIT, exitHandler) logging.info("Door Status Listener started") if len(sys.argv) > 1: - socketfile = sys.argv[1] -else: - socketfile = "/var/run/tuer/door_cmd.socket" - -if len(sys.argv) > 2: - uwscfg = UWSConfig(sys.argv[2]) + uwscfg = UWSConfig(sys.argv[1]) else: uwscfg = UWSConfig() -sendXmppMsg(uwscfg.xmpp_recipients_debug,"D: update-web-status.py started") +if len(sys.argv) > 2: + if sys.argv[2] == "open": + displayOpen() + elif sys.argv[2] == "closed": + displayClosed() + elif sys.argv[2] == "panic": + displayPanic() + print "Satus submitted to Web, now exiting..." + sys.exit(0) -sockhandle = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) -RE_STATUS = re.compile(r'Status: (\w+), idle') -RE_REQUEST = re.compile(r'Request: (\w+) (?:Card )?(.+)') -RE_ERROR = re.compile(r'Error: (.+)') +#socket.setdefaulttimeout(10.0) #affects all new Socket Connections (urllib as well) +RE_PRESENCE = re.compile(r'Presence: (yes|no)(?:, (opened|closed), (.+))?') +RE_BUTTON = re.compile(r'PanicButton|button\d?') while True: try: - sockhandle.connect(socketfile) + if not os.path.exists(uwscfg.tracker_socket): + logging.debug("Socketfile '%s' not found, waiting 5 secs" % uwscfg.tracker_socket) + time.sleep(5) + continue + sockhandle = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sockhandle.connect(uwscfg.tracker_socket) conn = os.fdopen(sockhandle.fileno()) - sockhandle.send("listen\n") - sockhandle.send("status\n") + #sockhandle.send("listen\n") + #sockhandle.send("status\n") + last_status=None + unixts_panic_button=None while True: line = conn.readline() logging.debug("Got Line: " + line) uwscfg.checkConfigUpdates() - m = RE_STATUS.match(line) + if line == "": + raise Exception("EOF on Socket, daemon seems to have quit") + + m = RE_PRESENCE.match(line) if not m is None: status = m.group(1) - if status == "opened": + last_status=(status == "yes") + unixts_panic_button=None + if last_status: displayOpen() - if status == "closed": + else: displayClosed() - m = RE_REQUEST.match(line) - if not m is None: - #(rq_action,rq_by) = m.group(1,2) - action_by = " von " + m.group(2) - else: - action_by = "" - m = RE_ERROR.match(line) + continue + + m = RE_BUTTON.match(line) if not m is None: - errorstr = m.group(1) - if "too long!" in errorstr: - distributeXmppMsg(uwscfg.xmpp_recipients_debug, "Door Error: "+errorstr, high_priority=True) + displayPanic() + unixts_panic_button=time.time() + continue + + if not last_status is None and not unixts_panic_button is None and time.time() - unixts_panic_button > 3600: + unixts_panic_button=None + if last_status: + displayOpen() else: - sendXmppMsg(uwscfg.xmpp_recipients_debug, "D: Error: "+errorstr) + displayClosed() + continue + except Exception, ex: - logging.error(str(ex)) - try: - conn.close() - except: - pass + logging.error("main: "+str(ex)) try: sockhandle.close() except: pass + conn=None + sockhandle=None time.sleep(5) -