From c1d893877efb1c5edd24dbd5bb8fc41379c01ebf Mon Sep 17 00:00:00 2001 From: Bernhard Tittelbach Date: Mon, 26 Jul 2010 22:43:50 +0000 Subject: [PATCH] play sound and others --- play-sound-status.py | 249 ++++++++++++++++++++++++++++++++++++++++ powersensordaemon/powerids.txt | 4 +- powersensordaemon/switch.cgi | 18 ++- track-presence.py | 1 + 4 files changed, 267 insertions(+), 5 deletions(-) create mode 100755 play-sound-status.py diff --git a/play-sound-status.py b/play-sound-status.py new file mode 100755 index 0000000..ea193f2 --- /dev/null +++ b/play-sound-status.py @@ -0,0 +1,249 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import os +import os.path +import sys +#import threading +import logging +import logging.handlers +import urllib +import time +import signal +import re +import socket +import subprocess +import types +import ConfigParser + +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('playsound') + self.config_parser.set('playsound','remote_cmd',"ssh -i /flash/tuer/id_rsa -o PasswordAuthentication=no -o StrictHostKeyChecking=no %RHOST% %RCMD%") + self.config_parser.set('playsound','remote_host',"root@slug.realraum.at") + self.config_parser.set('playsound','remote_cmd',"/home/playmp3.sh /home/half-life-door.mp3") + 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: + cf_handle = open(self.configfile,"r") + cf_handle.close() + except IOError: + self.writeConfigFile() + else: + 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,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, 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: + return + logging.debug("Writing Configfile "+self.configfile) + try: + cf_handle = open(self.configfile,"w") + self.config_parser.write(cf_handle) + cf_handle.close() + self.config_mtime=os.path.getmtime(self.configfile) + except IOError, io_ex: + logging.error("Error writing Configfile: "+str(io_ex)) + self.configfile=None + + def __getattr__(self, name): + underscore_pos=name.find('_') + if underscore_pos < 0: + raise AttributeError + try: + return self.config_parser.get(name[0:underscore_pos], name[underscore_pos+1:]) + except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): + raise AttributeError + + + +def playRemoteSound(uwscfg): + global sshp + uwscfg.checkConfigUpdates() + sshp = None + try: + cmd = uwscfg.sensors_remote_cmd.replace("%RHOST%",uwscfg.playsound_remote_host).replace("%RCMD%",uwscfg.playsound_remote_cmd).split(" ") + logging.debug("playRemoteSound: Executing: "+" ".join(cmd)) + sshp = subprocess.Popen(cmd, bufsize=1024, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) + logging.debug("playRemoteSound: pid %d: running=%d" % (sshp.pid,sshp.poll() is None)) + if not sshp.poll() is None: + raise Exception("playRemoteSound: subprocess %d not started ?, returncode: %d" % (sshp.pid,sshp.returncode)) + except Exception, ex: + logging.error("playRemoteSound: "+str(ex)) + traceback.print_exc(file=sys.stdout) + if not sshp is None and sshp.poll() is None: + if sys.hexversion >= 0x020600F0: + sshp.terminate() + else: + subprocess.call(["kill",str(sshp.pid)]) + time.sleep(1.5) + if sshp.poll() is None: + logging.error("playRemoteSound: subprocess still alive, sending SIGKILL to pid %d" % (sshp.pid)) + if sys.hexversion >= 0x020600F0: + sshp.kill() + else: + subprocess.call(["kill","-9",str(sshp.pid)]) + time.sleep(5) + + + +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 + +def popenTimeout2(cmd, pinput, returncode_ok=[0], ptimeout=21): + logging.debug("popenTimeout2: starting: " + cmd) + try: + 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("popenTimeout2: "+str(e)) + try: + signal.signal(signal.SIGALRM, old_shandler) + except: + pass + return False + +def exitHandler(signum, frame): + logging.info("Update-Web-Status stopping") + try: + conn.close() + except: + pass + try: + sockhandle.close() + except: + pass + sys.exit(0) + +#signals proapbly don't work because of readline +#signal.signal(signal.SIGTERM, exitHandler) +signal.signal(signal.SIGINT, exitHandler) +signal.signal(signal.SIGQUIT, exitHandler) + +logging.info("Door Status Listener 'PlaySound' started") + +if len(sys.argv) > 1: + uwscfg = UWSConfig(sys.argv[1]) +else: + uwscfg = UWSConfig() + +#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: + 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") + last_status=None + unixts_panic_button=None + while True: + line = conn.readline() + logging.debug("Got Line: " + line) + + uwscfg.checkConfigUpdates() + + 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) + last_status=(status == "yes") + unixts_panic_button=None + if last_status: + playRemoteSound() + continue + + m = RE_BUTTON.match(line) + if not m is None: + pass #insert panic action here + continue + + except Exception, ex: + logging.error("main: "+str(ex)) + try: + sockhandle.close() + except: + pass + conn=None + sockhandle=None + time.sleep(5) diff --git a/powersensordaemon/powerids.txt b/powersensordaemon/powerids.txt index a9f59c3..3376902 100644 --- a/powersensordaemon/powerids.txt +++ b/powersensordaemon/powerids.txt @@ -1,12 +1,12 @@ werkzeug a -stereo b +stereo 1 labor c dart d logo e idee f deckehinten g deckevorne h -all abcdefgh +all a1cdefgh decke gh lichter acdfgh ymhpower 1 diff --git a/powersensordaemon/switch.cgi b/powersensordaemon/switch.cgi index 648de32..122e831 100755 --- a/powersensordaemon/switch.cgi +++ b/powersensordaemon/switch.cgi @@ -16,14 +16,21 @@ for QUERY in `echo $QUERY_STRING | tr '&' ' '`; do done UNIXSOCK=/var/run/powersensordaemon/cmd.sock -VALIDIDS="werkzeug stereo labor schreibtisch logo idee deckehinten deckevorne decke lichter all" - +VALIDIDS="decke lichter all werkzeug stereo labor dart logo idee deckehinten deckevorne ymhvolup ymhvoldown ymhcd ymhwdtv ymhtuner" if [ "$POWER" == "on" -o "$POWER" == "off" ]; then for CHECKID in $VALIDIDS; do if [ "$CHECKID" == "$ID" ]; then echo "power $POWER $ID" | usocket $UNIXSOCK + echo "Content-type: text/html" + echo "" + echo "" + echo "" + echo "Realraum rf433ctl" + echo '' + echo "" + exit 0 fi done fi @@ -31,7 +38,7 @@ fi DESC_werkzeug="Werkzeug LEDs" DESC_stereo="Stereo Anlage" DESC_labor="Labor Licht" -DESC_schreibtisch="Schreibtisch Licht" +DESC_dart="Dart Scheibe" DESC_logo="Logo" DESC_idee="Idee" DESC_deckehinten="Decke Hinten" @@ -39,6 +46,11 @@ DESC_deckevorne="Decke Vorne" DESC_decke="Deckenlichter" DESC_lichter="Alle Lichter" DESC_all="Alles" +DESC_yhmvolup="VolumeUp" +DESC_yhmvoldown="VolumeDown" +DESC_ymhcd="Input CD" +DESC_ymhwdtv="Input WDlxTV" +DESC_ymhtuner="Input Tuner" echo "Content-type: text/html" echo "" diff --git a/track-presence.py b/track-presence.py index 9f0aa66..91b0123 100755 --- a/track-presence.py +++ b/track-presence.py @@ -321,6 +321,7 @@ class StatusTracker: #(threading.Thread): self.lock.acquire() self.door_open_previously = self.door_open self.lock.release() + loggin.debug("doorOpen: open: %s, who: %s, how:%s, manual_switch: %s; physically_present: %s" % (self.door_open,self.door_who,how,self.door_manual_switch_used,self.door_manual_switch_used)); def doorClosed(self,who,how): self.uwscfg.checkConfigUpdates() -- 1.7.10.4