From 1a4cfcb948037754b908d0be876fdee02dca2eec Mon Sep 17 00:00:00 2001 From: Bernhard Tittelbach Date: Fri, 26 Mar 2010 15:24:15 +0000 Subject: [PATCH] mehr presence intelligenz, weniger xmpp messages --- switch-power.py | 14 +++- track-presence.py | 202 ++++++++++++++++++++++++++++++++++++------------- update-web-status.py | 21 ++++- update-xmpp-status.py | 125 ++++++++++++++---------------- 4 files changed, 235 insertions(+), 127 deletions(-) diff --git a/switch-power.py b/switch-power.py index 1ee8421..287cf76 100755 --- a/switch-power.py +++ b/switch-power.py @@ -36,7 +36,7 @@ class UWSConfig: self.config_parser.set('slug','ids_nonpresent_off','idee schreibtisch labor werkzeug stereo logo') #self.config_parser.set('slug','time_day','6:00-17:00') self.config_parser.add_section('debug') - self.config_parser.set('debug','enabled',"True") + 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 @@ -110,21 +110,27 @@ def switchPower(powerid,turn_on=False): onoff="off" touchURL(uwscfg.slug_cgiuri.replace("%ID%",powerid).replace("%ONOFF%",onoff)) +######### EVENTS ############### + def eventPresent(): hour = datetime.datetime.now().hour if hour > 6 and hour < 18: present_ids=uwscfg.slug_ids_present_day else: present_ids=uwscfg.slug_ids_present_night + logging.info("event: someone present, switching on: "+present_ids) for id in present_ids.split(" "): switchPower(id,True) def eventNobodyHere(): - for id in uwscfg.slug_ids_nonpresent_off.split(" "): + present_ids=uwscfg.slug_ids_nonpresent_off + logging.info("event: noone here, switching off: "+present_ids) + for id in present_ids.split(" "): switchPower(id,False) switchPower(id,False) def eventPanic(): + logging.info("event: Panic:, switching around: "+uwscfg.slug_ids_panic) lst1 = uwscfg.slug_ids_panic.split(" ") lst2 = lst1 lst2.append(lst2.pop(0)) @@ -141,6 +147,8 @@ def eventPanic(): switchPower(id,False) eventPresent() +######################## + def exitHandler(signum, frame): logging.info("Power Switch Daemon stopping") try: @@ -166,7 +174,7 @@ else: uwscfg = UWSConfig() #socket.setdefaulttimeout(10.0) #affects all new Socket Connections (urllib as well) -RE_PRESENCE = re.compile(r'Presence: (yes|no)') +RE_PRESENCE = re.compile(r'Presence: (yes|no)(?:, (opened|closed), (.+))?') RE_BUTTON = re.compile(r'PanicButton|button\d?') while True: try: diff --git a/track-presence.py b/track-presence.py index abd529e..c8f1b50 100755 --- a/track-presence.py +++ b/track-presence.py @@ -46,11 +46,11 @@ class UWSConfig: self.config_parser.set('sensors','remote_socket',"/var/run/powersensordaemon/cmd.sock") self.config_parser.set('sensors','remote_shell',"usocket") self.config_parser.add_section('tracker') - self.config_parser.set('tracker','sec_wait_movement_after_door_closed',"15.0") - self.config_parser.set('tracker','sec_general_movement_timeout',3600) + self.config_parser.set('tracker','sec_necessary_to_move_through_door',"10.0") + self.config_parser.set('tracker','sec_general_movement_timeout',"3600") self.config_parser.set('tracker','server_socket',"/var/run/tuer/presence.socket") - self.config_parser.set('tracker','photo_flashlight',950) - self.config_parser.set('tracker','photo_artif_light',150) + self.config_parser.set('tracker','photo_flashlight',"950") + self.config_parser.set('tracker','photo_artif_light',"150") self.config_parser.add_section('debug') self.config_parser.set('debug','enabled',"False") self.config_mtime=0 @@ -141,13 +141,15 @@ class UWSConfig: ######## Status Listener Threads ############ +threads_running=True def trackSensorStatusThread(uwscfg,status_tracker,connection_listener): + global sshp, threads_running #RE_TEMP = re.compile(r'temp\d: (\d+\.\d+)') - RE_PHOTO = re.compile(r'photo\d: .*(\d+)') + RE_PHOTO = re.compile(r'photo\d: [^0-9]*?(\d+)') RE_MOVEMENT = re.compile(r'movement|button\d?|PanicButton') RE_ERROR = re.compile(r'Error: (.+)') - while True: + while threads_running: uwscfg.checkConfigUpdates() sshp = None try: @@ -166,7 +168,7 @@ def trackSensorStatusThread(uwscfg,status_tracker,connection_listener): sshp.stdin.write("listen sensor\n") #sshp.stdin.write("sample temp0\n") sshp.stdin.flush() - while True: + while threads_running: if not sshp.poll() is None: raise Exception("trackSensorStatusThread: subprocess %d finished, returncode: %d" % (sshp.pid,sshp.returncode)) line = sshp.stdout.readline() @@ -180,7 +182,7 @@ def trackSensorStatusThread(uwscfg,status_tracker,connection_listener): continue m = RE_PHOTO.match(line) if not m is None: - status_tracker.currentLightLevel(m.group(1)) + status_tracker.currentLightLevel(int(m.group(1))) continue m = RE_ERROR.match(line) if not m is None: @@ -201,29 +203,36 @@ def trackSensorStatusThread(uwscfg,status_tracker,connection_listener): else: subprocess.call(["kill","-9",str(sshp.pid)]) time.sleep(5) - +door_sockhandle=None +door_socklock=threading.Lock() def trackDoorStatusThread(uwscfg, status_tracker,connection_listener): + global door_sockhandle, door_socklock, threads_running #socket.setdefaulttimeout(10.0) #affects all new Socket Connections (urllib as well) RE_STATUS = re.compile(r'Status: (\w+), idle') - RE_REQUEST = re.compile(r'Request: (\w+) (?:Card )?(.+)') + RE_REQUEST = re.compile(r'Request: (\w+) (?:(Card|Phone) )?(.+)') RE_ERROR = re.compile(r'Error: (.+)') - while True: + while threads_running: uwscfg.checkConfigUpdates() - conn=None - sockhandle=None + with door_socklock: + conn=None + door_sockhandle=None try: if not os.path.exists(uwscfg.door_cmd_socket): logging.debug("Socketfile '%s' not found, waiting 5 secs" % uwscfg.door_cmd_socket) time.sleep(5) continue - sockhandle = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sockhandle.connect(uwscfg.door_cmd_socket) - conn = os.fdopen(sockhandle.fileno()) - sockhandle.send("listen\n") - sockhandle.send("status\n") - last_who=None - while True: + with door_socklock: + door_sockhandle = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + door_sockhandle.connect(uwscfg.door_cmd_socket) + conn = os.fdopen(door_sockhandle.fileno()) + door_sockhandle.send("listen\n") + door_sockhandle.send("status\n") + + last_who = None + last_how = None + while threads_running: + #no lock here, we're just blocking and reading line = conn.readline() logging.debug("trackDoorStatusThread: Got Line: " + line) @@ -236,27 +245,37 @@ def trackDoorStatusThread(uwscfg, status_tracker,connection_listener): if not m is None: status = m.group(1) if status == "opened": - status_tracker.doorOpen(last_who) + status_tracker.doorOpen(last_who, last_how) if status == "closed": - status_tracker.doorClosed(last_who) + status_tracker.doorClosed(last_who, last_how) last_who = None + last_how = None continue m = RE_REQUEST.match(line) if not m is None: - last_who = m.group(2) + last_who = m.group(3) + last_how = m.group(2) continue except Exception, ex: logging.error("main: "+str(ex)) traceback.print_exc(file=sys.stdout) try: - if not sockhandle is None: - sockhandle.close() + with door_socklock: + if not door_sockhandle is None: + door_sockhandle.close() except: pass - conn=None - sockhandle=None + with door_socklock: + conn=None + door_sockhandle=None time.sleep(5) +def updateDoorStatus(): + global door_sockhandle, door_socklock + with door_socklock: + if not door_sockhandle is None: + door_sockhandle.send("status\n") + ############ Status Tracker Class ############ class StatusTracker: #(threading.Thread): @@ -267,6 +286,8 @@ class StatusTracker: #(threading.Thread): self.door_open_previously=None self.door_open=False self.door_manual_switch_used=False + self.door_physically_present=True + self.door_who=None self.last_door_operation_unixts=0 self.last_movement_unixts=0 self.last_light_value=0 @@ -274,32 +295,38 @@ class StatusTracker: #(threading.Thread): self.lock=threading.Lock() #Notify State locked by self.presence_notify_lock self.last_somebody_present_result=False + self.last_warning=None + self.count_same_warning=0 self.presence_notify_lock=threading.Lock() #timer self.timer=None - def doorOpen(self,who): + def doorOpen(self,who,how): self.uwscfg.checkConfigUpdates() self.lock.acquire() self.door_open=True - if not self.door_open_previously is None: - self.door_manual_switch_used=(who is None or len(who) == 0) - self.last_door_operation_unixts=time.time() if self.door_open != self.door_open_previously: + self.door_who=who + self.door_manual_switch_used=(who is None or len(who) == 0) + self.door_physically_present=(self.door_manual_switch_used or how == "Card") + if not self.door_open_previously is None: + self.last_door_operation_unixts=time.time() self.lock.release() self.checkPresenceStateChangeAndNotify() self.lock.acquire() self.door_open_previously = self.door_open self.lock.release() - def doorClosed(self,who): + def doorClosed(self,who,how): self.uwscfg.checkConfigUpdates() self.lock.acquire() self.door_open=False - if not self.door_open_previously is None: - self.door_manual_switch_used=(who is None or len(who) == 0) - self.last_door_operation_unixts=time.time() if self.door_open != self.door_open_previously: + self.door_who=who + self.door_manual_switch_used=(who is None or len(who) == 0) + self.door_physically_present=(self.door_manual_switch_used or how == "Card") + if not self.door_open_previously is None: + self.last_door_operation_unixts=time.time() self.lock.release() self.checkPresenceStateChangeAndNotify() self.lock.acquire() @@ -333,32 +360,66 @@ class StatusTracker: #(threading.Thread): else: return "Light: off" + + def checkAgainIn(self, sec): + #~ if not self.timer is None: + #~ logging.debug("checkAgainIn: canceled previous running Timer") + #~ self.timer.cancel() + logging.debug("checkAgainIn: starting Timer with timeout %fs" % sec) + self.timer=threading.Timer(sec, self.checkPresenceStateChangeAndNotify) + self.timer.start() #TODO: check brightness level from cam or an arduino sensor def somebodyPresent(self): - global uwscfg with self.lock: - if (self.door_open): - return True - elif (time.time() - self.last_door_operation_unixts <= float(self.uwscfg.tracker_sec_wait_movement_after_door_closed)): + if self.door_open: + if self.door_physically_present: + return True + elif self.last_movement_unixts > self.last_door_operation_unixts: + return True + else: + return False + elif time.time() - self.last_door_operation_unixts <= float(self.uwscfg.tracker_sec_necessary_to_move_through_door): #start timer, checkPresenceStateChangeAndNotify after tracker_sec_wait_movement - if not self.timer is None: - self.timer.cancel() - self.timer=threading.Timer(float(self.uwscfg.tracker_sec_wait_movement_after_door_closed), self.checkPresenceStateChangeAndNotify) - self.timer.start() - return True - elif (self.last_movement_unixts > self.last_door_operation_unixts and (self.door_manual_switch_used or ( time.time() - self.last_movement_unixts < float(self.uwscfg.tracker_sec_general_movement_timeout)))): + self.checkAgainIn(float(self.uwscfg.tracker_sec_necessary_to_move_through_door)) + return self.last_somebody_present_result + elif self.last_movement_unixts > self.last_door_operation_unixts and (self.door_manual_switch_used or ( time.time() - self.last_movement_unixts < float(self.uwscfg.tracker_sec_general_movement_timeout))): return True else: return False + def getPossibleWarning(self): + with self.lock: + somebody_present=self.last_somebody_present_result + if self.door_open and not somebody_present and time.time() - self.last_door_operation_unixts >= 2* float(self.uwscfg.tracker_sec_necessary_to_move_through_door): + return "Door opened recently but nobody present" + elif self.door_open and not somebody_present: + self.checkAgainIn(2*float(self.uwscfg.tracker_sec_necessary_to_move_through_door)) + return None + elif not somebody_present and self.last_light_unixts > self.last_door_operation_unixts and self.last_light_value > int(self.uwscfg.tracker_photo_artif_light): + return "Nobody here but light is still on" + else: + return None + def checkPresenceStateChangeAndNotify(self): with self.presence_notify_lock: somebody_present = self.somebodyPresent() + logging.debug("checkPresenceStateChangeAndNotify: somebody_present=%s, door_open=%s, who=%s, light=%s" % (somebody_present,self.door_open,self.door_who, str(self.last_light_value))) if somebody_present != self.last_somebody_present_result: self.last_somebody_present_result = somebody_present if not self.status_change_handler is None: - self.status_change_handler(somebody_present) + self.status_change_handler(somebody_present, door_open=self.door_open, who=self.door_who) + warning = self.getPossibleWarning() + if warning == self.last_warning: + self.count_same_warning+=1 + else: + self.last_warning=warning + self.count_same_warning=0 + if not warning is None and self.count_same_warning < 3: + logging.debug("checkPresenceStateChangeAndNotify: warning: " + str(warning)) + if not self.status_change_handler is None: + self.status_change_handler(somebody_present=None, door_open=self.door_open, who=self.door_who, warning=warning) + ############ Connection Listener ############ class ConnectionListener: @@ -373,14 +434,37 @@ class ConnectionListener: self.client_sockets=[] self.lock=threading.Lock() - def statusString(self,somebody_present): + def shutdown(self): + self.running=False + try: + self.server_socket.close() + except: + pass + with self.lock: + for sock_to_close in self.client_sockets: + try: + sock_to_close.close() + except: + pass + + def statusString(self,somebody_present, door_open=None, who=None): + details="" + if not who is None: + if door_open: + details=", opened, " + else: + details=", closed, " + details += who if somebody_present: - return "Presence: yes" + "\n" + return "Presence: yes" + details + "\n" else: - return "Presence: no" + "\n" + return "Presence: no" + details + "\n" - def updateStatus(self,somebody_present): - self.distributeData(self.statusString(somebody_present)) + def updateStatus(self,somebody_present=None,door_open=None,who=None,warning=None): + if not somebody_present is None: + self.distributeData(self.statusString(somebody_present, door_open, who)) + if not warning is None: + self.distributeData("Warning: " + warning + "\n") def distributeData(self,data): with self.lock: @@ -403,6 +487,7 @@ class ConnectionListener: newsocketconn.send(self.statusString(self.status_tracker.somebodyPresent())) with self.lock: self.client_sockets.append(newsocketconn) + updateDoorStatus() else: #drop all recieved data and watch for closed sockets if not socket_to_read.recv(256): @@ -417,7 +502,22 @@ class ConnectionListener: ############ Main Routine ############ def exitHandler(signum, frame): + global threads_running, connection_listener, sshp, door_sockhandle logging.info("Track Presence stopping") + threads_running=False + connection_listener.shutdown() + try: + if sys.hexversion >= 0x020600F0: + sshp.terminate() + else: + subprocess.call(["kill",str(sshp.pid)]) + except: + pass + try: + door_sockhandle.close() + except: + pass + time.sleep(0.1) sys.exit(0) #signals proapbly don't work because of readline diff --git a/update-web-status.py b/update-web-status.py index 8bdd4aa..78e3d71 100755 --- a/update-web-status.py +++ b/update-web-status.py @@ -195,8 +195,7 @@ else: uwscfg = UWSConfig() #socket.setdefaulttimeout(10.0) #affects all new Socket Connections (urllib as well) -#RE_STATUS = re.compile(r'Status: (\w+), idle') -RE_PRESENCE = re.compile(r'Presence: (yes|no)') +RE_PRESENCE = re.compile(r'Presence: (yes|no)(?:, (opened|closed), (.+))?') RE_BUTTON = re.compile(r'PanicButton|button\d?') while True: try: @@ -209,6 +208,8 @@ while True: conn = os.fdopen(sockhandle.fileno()) #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) @@ -221,16 +222,28 @@ while True: m = RE_PRESENCE.match(line) if not m is None: status = m.group(1) - if status == "yes": + last_status=(status == "yes") + unixts_panic_button=None + if last_status: displayOpen() else: displayClosed() continue + m = RE_BUTTON.match(line) if not m is None: 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: + displayClosed() + continue + except Exception, ex: logging.error("main: "+str(ex)) try: diff --git a/update-xmpp-status.py b/update-xmpp-status.py index 7671300..06559e3 100755 --- a/update-xmpp-status.py +++ b/update-xmpp-status.py @@ -3,7 +3,6 @@ import os import os.path import sys -#import threading import logging import logging.handlers import urllib @@ -14,6 +13,7 @@ import socket import subprocess import types import ConfigParser +import traceback logger = logging.getLogger() logger.setLevel(logging.INFO) @@ -34,14 +34,10 @@ class UWSConfig: self.config_parser.set('xmpp','recipients_nooffline','the-equinox@jabber.org davrieb@jabber.ccc.de') self.config_parser.add_section('msg') self.config_parser.set('msg','bored',"The Button has been pressed ! Maybe somebody want's company. Go Visit !") - self.config_parser.set('msg','format',"${status_msg}${request_msg}${comment_msg}") - self.config_parser.set('msg','status_opened_msg',"RealRaum door now open") - self.config_parser.set('msg','status_closed_msg',"RealRaum door now closed") + self.config_parser.set('msg','present',"Somebodys presence has been detected${door_action_msg}") + self.config_parser.set('msg','notpresent',"Nobody seems to be here, guess everybody left${door_action_msg}") + self.config_parser.set('msg','door_action_msg',", door ${door_status} ${by_whom}") self.config_parser.set('msg','status_error_msg',"ERROR Last Operation took too long !!!") - self.config_parser.set('msg','request_msg',"\safter ${request} request") - self.config_parser.set('msg','comment_msg',"\s(${comment})") - self.config_parser.set('msg','status_still_opened_msg',"Door remains closed") - self.config_parser.set('msg','status_still_closed_msg',"Door remains open") self.config_parser.add_section('tracker') self.config_parser.set('tracker','socket',"/var/run/tuer/presence.socket") self.config_parser.add_section('debug') @@ -72,13 +68,6 @@ class UWSConfig: self.config_mtime=os.path.getmtime(self.configfile) except (ConfigParser.ParsingError, IOError), pe_ex: logging.error("Error parsing Configfile: "+str(pe_ex)) - self.config_parser.set('msg','comment_msg', self.config_parser.get('msg','comment_msg').replace("\\s"," ")) - self.config_parser.set('msg','request_msg', self.config_parser.get('msg','request_msg').replace("\\s"," ")) - self.config_parser.set('msg','status_error_msg', self.config_parser.get('msg','status_error_msg').replace("\\s"," ")) - self.config_parser.set('msg','status_closed_msg', self.config_parser.get('msg','status_closed_msg').replace("\\s"," ")) - self.config_parser.set('msg','status_opened_msg', self.config_parser.get('msg','status_opened_msg').replace("\\s"," ")) - self.config_parser.set('msg','status_still_closed_msg', self.config_parser.get('msg','status_still_closed_msg').replace("\\s"," ")) - self.config_parser.set('msg','status_still_opened_msg', self.config_parser.get('msg','status_still_opened_msg').replace("\\s"," ")) if self.config_parser.get('debug','enabled') == "True": logger.setLevel(logging.DEBUG) else: @@ -137,6 +126,7 @@ def popenTimeout1(cmd, pinput, returncode_ok=[0], ptimeout = 20.0, pcheckint = 0 return False def popenTimeout2(cmd, pinput, returncode_ok=[0], ptimeout=21): + global sppoo logging.debug("popenTimeout2: starting: " + cmd) try: sppoo = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=True) @@ -183,7 +173,6 @@ def sendXmppMsg(recipients, msg, resource = "torwaechter", addtimestamp = True, popenTimeout2(sendxmpp_cmd, msg) - def distributeXmppMsg(msg,high_priority=False,debug=False): if debug == False: sendXmppMsg(uwscfg.xmpp_recipients_normal, msg) @@ -191,59 +180,44 @@ def distributeXmppMsg(msg,high_priority=False,debug=False): else: sendXmppMsg(uwscfg.xmpp_recipients_debug, "D: " + msg) -def formatAndDistributePresence(presence): +def substituteMessageVariables(msg, door_tuple): + loop_tokens=3 + while loop_tokens > 0 and msg.find("${") > -1: + #logging.debug("subsMsgVars: loopTok=%d door_tuple=%s msg=%s" % (loop_tokens, str(door_tuple), msg)) + if not door_tuple is None and type(door_tuple[0]) == types.StringType: + msg = msg.replace('${door_action_msg}', uwscfg.msg_door_action_msg) + msg = msg.replace('${door_status}', door_tuple[0]).replace('${by_whom}', "by "+str(door_tuple[1])) + else: + msg = msg.replace('${door_action_msg}','').replace('${door_status}','').replace('${by_whom}','') + loop_tokens-=1 + return msg + +def formatAndDistributePresence(presence, door_tuple=(None,None)): if presence == "yes": - distributeXmppMsg("Somebody is present right now") + distributeXmppMsg(substituteMessageVariables(uwscfg.msg_present, door_tuple)) else: - distributeXmppMsg("Nobody is here, everybody left") + distributeXmppMsg(substituteMessageVariables(uwscfg.msg_notpresent, door_tuple)) -current_status = (None, None, None) +def formatAndDistributeWarning(msg, door_tuple=(None,None)): + distributeXmppMsg("Warning: "+msg , high_priority=True) + +current_status = (None, None, None, None) def filterAndFormatMessage(new_status): global current_status - if new_status in [current_status, (current_status[0], None, None)] : - distributeXmppMsg("Status recieved but filtered: (%s,%s,%s)" % new_status ,debug=True) - elif current_status == (None, None, None): - current_status=new_status - distributeXmppMsg("Initial Status: (%s,%s,%s)" % new_status ,debug=True) - else: - (status,req,req_comment) = new_status - high_priority_msg = False - req_msg="" - status_msg="" - comment_msg="" - if status == "error": - status_msg = uwscfg.msg_status_error_msg - high_priority_msg=True - else: - if current_status[0] == status: - if status == "opened": - status_msg = uwscfg.msg_status_still_opened_msg - elif status == "closed": - status_msg = uwscfg.msg_status_still_closed_msg - else: - logging.error("Unknown Status recieved: (%s,%s,%s)" % new_status) - distributeXmppMsg("Unknown Status: (%s,%s,%s)" % new_status ,debug=True) - return - else: - if status == "opened": - status_msg = uwscfg.msg_status_opened_msg - elif status == "closed": - status_msg = uwscfg.msg_status_closed_msg - else: - logging.error("Unknown Status recieved: (%s,%s,%s)" % new_status) - distributeXmppMsg("Unknown Status: (%s,%s,%s)" % new_status ,debug=True) - return - if req: - req_msg = uwscfg.msg_request_msg.replace("${request}",req) - if req_comment: - comment_msg = uwscfg.msg_comment_msg.replace("${comment}",req_comment) - msg = uwscfg.msg_format.replace("${status_msg}", status_msg).replace("${request_msg}",req_msg).replace("${comment_msg}",comment_msg) - distributeXmppMsg(msg, high_priority=high_priority_msg) - current_status=new_status + if new_status[0] == "error": + distributeXmppMsg(uwscfg.msg_status_error_msg, high_priority=True) + elif current_status[0] != new_status[0]: + distributeXmppMsg("Status: (%s,%s,%s,%s)" % new_status ,debug=True) + current_status=new_status def exitHandler(signum, frame): + global sppoo, conn, sockhandle logging.info("Door Status Listener stopping") try: + sppoo.kill() + except: + pass + try: conn.close() except: pass @@ -267,10 +241,11 @@ else: distributeXmppMsg("update-xmpp-status.py started", debug=True) RE_STATUS = re.compile(r'Status: (\w+), idle') -RE_REQUEST = re.compile(r'Request: (\w+) (?:Card )?(.+)') -RE_PRESENCE = re.compile(r'Presence: (yes|no)') +RE_REQUEST = re.compile(r'Request: (\w+) (?:(Card|Phone) )?(.+)') +RE_PRESENCE = re.compile(r'Presence: (yes|no)(?:, (opened|closed), (.+))?') RE_BUTTON = re.compile(r'PanicButton|button\d?') RE_ERROR = re.compile(r'Error: (.+)') +RE_WARNING = re.compile(r'Warning: (.+)') while True: try: if not os.path.exists(uwscfg.tracker_socket): @@ -282,7 +257,7 @@ while True: conn = os.fdopen(sockhandle.fileno()) #sockhandle.send("listen\n") #sockhandle.send("status\n") - last_request = (None, None) + last_request = (None, None, None) not_initial_presence = False while True: line = conn.readline() @@ -296,37 +271,49 @@ while True: m = RE_BUTTON.match(line) if not m is None: distributeXmppMsg(uwscfg.msg_bored) - continue + continue + m = RE_PRESENCE.match(line) if not m is None: if not_initial_presence: - formatAndDistributePresence(m.group(1)) + formatAndDistributePresence(m.group(1), m.group(2,3)) else: not_initial_presence=True distributeXmppMsg("Initial Presence received: %s" % m.group(1) ,debug=True) continue + + m = RE_WARNING.match(line) + if not m is None: + errorstr = m.group(1) + logging.error("Recieved Warning: "+errorstr) + formatAndDistributeWarning(errorstr) + continue + m = RE_STATUS.match(line) if not m is None: status = m.group(1) filterAndFormatMessage((status,) + last_request) - last_request = (None, None) + last_request = (None, None, None) continue + m = RE_REQUEST.match(line) if not m is None: - last_request = m.group(1,2) + last_request = m.group(1,3,2) continue + m = RE_ERROR.match(line) if not m is None: errorstr = m.group(1) if "too long!" in errorstr: filterAndFormatMessage(("error",) + last_request) - last_request = (None, None) + last_request = (None, None, None) else: logging.error("Recieved Error: "+errorstr) distributeXmppMsg("Error: "+errorstr, debug=True) - last_request = (None, None) + last_request = (None, None, None) except Exception, ex: logging.error("main: "+str(ex)) + traceback.print_exc(file=sys.stdout) try: sockhandle.close() except: -- 1.7.10.4