changed temp/photo listener to sensor listener
[svn42.git] / door_daemon.py
index 903d6cf..f17083b 100755 (executable)
@@ -8,101 +8,116 @@ import urllib
 import time
 import signal
 import re
+import socket
+import serial
 
-logging.basicConfig(level=logging.INFO,filename='/var/log/tuer.log')
+logging.basicConfig(level=logging.INFO,filename='/var/log/tmp/tuer.log',format="%(asctime)s %(message)s",datefmt="%Y-%m-%d %H:%M")
 
-class StatusDisplay(object):
-   def __init__(self):
-    self.url_open = 'https://www.realraum.at/cgi/status.cgi?pass=jako16&set=%3Chtml%3E%3Cbody%20bgcolor=%22lime%22%3E%3Ch3%3E%3Ccenter%3ETuer%20ist%20Offen%3C/center%3E%3C/h3%3E%3C/body%3E%3C/html%3E';
-    self.url_closed = 'https://www.realraum.at/cgi/status.cgi?pass=jako16&set=%3Chtml%3E%3Cbody%20bgcolor=%22red%22%3E%3Ch3%3E%3Ccenter%3ETuer%20ist%20Geschlossen%3C/center%3E%3C/h3%3E%3C/body%3E%3C/html%3E';
-    self.last_status_set=self.url_open
+class StatusDisplay():
+  def __init__(self):
+    self.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.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.last_status_set=""
     #object.__init__(self)
     
-    def display_open(self):
-      if self.last_status_set != self.url_open:
-        self.last_status_set=self.url_open
+  def display_open(self):
+    if self.last_status_set != self.url_open:
+      self.last_status_set=self.url_open
+      try:
+        #print "accessing %s\n" % self.last_status_set
         f = urllib.urlopen(self.last_status_set)
+        f.read()
         f.close()
-      
-    def display_closed(self):
-      if self.last_status_set != self.url_closed:
-        self.last_status_set=self.url_closed
+      except:
+        pass
+
+  def display_closed(self):
+    if self.last_status_set != self.url_closed:
+      self.last_status_set=self.url_closed
+      try:
+        #print "accessing %s\n" % self.last_status_set
         f = urllib.urlopen(self.last_status_set)
+        f.read()
         f.close()
-
+      except:
+        pass
 
 class ArduinoUSBThread ( threading.Thread ):
   def __init__(self, file_dev_ttyusb):
-    self.re_isidle = re.compile(r'open')
-    self.re_isopen = re.compile(r'open')
-    self.re_isclosed = re.compile(r'close|closing')
+    self.re_isidle = re.compile(r'idle')
+    self.re_isopen = re.compile(r'Status: opened, idle')
+    self.re_isclosed = re.compile(r'Status: closed, idle')
     self.re_toolong = re.compile(r'took too long!')
     self.min_seconds_between_reset=10;
     self.timestamp_send_reset=0;
     self.running=True
     self.lastline=""
     self.last_status=None
+    self.shortsleep = 0
     self.cv_updatestatus = threading.Condition(); #lock ist automatically created withing condition
     self.file_dev_ttyusb=file_dev_ttyusb
+    self.dev = serial.Serial(port=file_dev_ttyusb, baudrate=9600,timeout=60)
+    #pythons sucks just like perl: we need nonblock or we can't write to FileHandle while we block reading on same filehandle
     self.statusdisplay = StatusDisplay()
     threading.Thread.__init__(self)
     
   def stop(self):
     self.running=False
-    self.fh.close()
+    if (self.dev.isOpen()):
+      self.dev.close()
 
   def send_open(self):
     self.send_statusrequest()
     self.cv_updatestatus.acquire()
-    self.cv_updatestatus.wait(3.0)
-    self.cv_updatestatus.release()
-    if re_isidle.search(self.lastline):
+    if self.re_isidle.search(self.lastline):
       logging.info("Opening Door")
-      self.fh.write("o");
+      self.dev.write("o");
+    self.cv_updatestatus.release()
     
   def send_close(self):
     self.send_statusrequest()
     self.cv_updatestatus.acquire()
-    self.cv_updatestatus.wait(3.0)
-    self.cv_updatestatus.release()    
-    if re_isidle.search(self.lastline):
+    if self.re_isidle.search(self.lastline):
       logging.info("Closing Door")
-      self.fh.write("c");
+      self.dev.write("c");
+    self.cv_updatestatus.release()
       
   def send_toggle(self):
     self.send_statusrequest()
     self.cv_updatestatus.acquire()
-    self.cv_updatestatus.wait(3.0)
+    if self.re_isidle.search(self.lastline):
+      logging.info("Toggling Door")
+      self.dev.write("t");
     self.cv_updatestatus.release()
-    if re_isidle.search(self.lastline):
-      if self.last_status == "open":
-        logging.info("Closing Door")
-        self.fh.write("c");
-      elif self.last_status == "closed":
-        logging.info("Opening Door")
-        self.fh.write("o");
-      
+    
   def send_reset(self):
-    logging.info("Resetting Door")
-    self.fh.write("r");
+    self.shortsleep = 20
+    logging.info("Resetting Door")    
+    self.dev.write("r");
 
   def send_statusrequest(self):
-    self.fh.write("s");
+    self.shortsleep = 20
+    self.dev.write("s");
+    self.cv_updatestatus.acquire()
+    self.cv_updatestatus.wait(5.0)
+    self.cv_updatestatus.release()        
 
   def run (self):
-    self.fh = open(self.file_dev_ttyusb,"rw")
-    while (self.running):
-      print "."
-      line = self.fh.readline();
+    if not self.dev.isOpen():
+      self.dev.open()
+    while (self.running and self.dev.isOpen()):
+      line = self.dev.readline()
+      if len(line) == 0:
+        continue
       self.cv_updatestatus.acquire()
-      self.lastline=line
+      self.lastline=line.strip()
       logging.info(self.file_dev_ttyusb+": "+self.lastline)
       if self.re_isclosed.search(self.lastline):
         self.last_status="closed"
-        self.statusdisplay.display_open()
+        self.statusdisplay.display_closed()
       elif self.re_isopen.search(self.lastline):
         self.last_status="open"
-        self.statusdisplay.display_closed()
+        self.statusdisplay.display_open()
       elif self.re_toolong.search(self.lastline):
         self.last_status="error"
         if (time.time() - self.timestamp_send_reset) > self.min_seconds_between_reset:
@@ -110,8 +125,8 @@ class ArduinoUSBThread ( threading.Thread ):
           self.send_reset()
       self.cv_updatestatus.notifyAll()
       self.cv_updatestatus.release()
-    if self.fh:
-      self.fh.close()
+    if self.dev.isOpen():
+      self.dev.close()
 
 class ControlFIFOThread ( threading.Thread ):
   def __init__(self, file_fifo, arduino):
@@ -123,53 +138,69 @@ class ControlFIFOThread ( threading.Thread ):
   
   def stop(self):
     self.running=False
-    self.fh.close()
+    self.dev.close()
   
   def run (self):
-    self.fh = open(self.file_fifo,"r")
+    self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    try:
+        os.remove(self.file_fifo)
+    except OSError:
+        pass
+    self.socket.bind(self.file_fifo)
+    self.socket.listen(1)
     while (self.running):
-      print "."
-      line=self.fh.readline()
-      m = self.re_cmd.match(line)
-      if not m is None:
-        (cmd,who) = m.group(1,2)
-        if cmd == "open":
-          logging.info("Open Requested by %s" % who)
-          arduino.send_open()
-        elif cmd == "close":
-          logging.info("Close Requested by %s" % who)
-          arduino.send_close()
-        elif cmd == "toggle":
-          logging.info("Toggle Requested by %s" % who)
-          arduino.send_toggle()
-        elif cmd == "reset":
-          logging.info("Reset Requested by %s" % who)
-          arduino.send_reset()
-        elif cmd == "status":
-          arduino.send_statusrequest()
-        elif cmd == "log":
-          logging.info(who)
-        else:
-          logging.info("Invalid Command %s %s" % (cmd,who))
-    if self.fh:
-      self.fh.close()
-
+      self.socketconn, addr = self.socket.accept()
+      self.conn = os.fdopen(self.socketconn.fileno())
+      while 1:
+        #~ line=""
+        #~ while 1:
+          #~ print "d"
+          #~ data = self.conn.recv(1024)
+          #~ if not data: 
+            #~ break
+          #~ else:
+            #~ line+= data
+        line=self.conn.readline()
+        if not line:
+          break
+        m = self.re_cmd.match(line)
+        if not m is None:
+          (cmd,who) = m.group(1,2)
+          if cmd == "open":
+            logging.info("Open Requested by %s" % who)
+            arduino.send_open()
+          elif cmd == "close":
+            logging.info("Close Requested by %s" % who)
+            arduino.send_close()
+          elif cmd == "toggle":
+            logging.info("Toggle Requested by %s" % who)
+            arduino.send_toggle()
+          elif cmd == "reset":
+            logging.info("Reset Requested by %s" % who)
+            arduino.send_reset()
+          elif cmd == "status":
+            arduino.send_statusrequest()
+            
+          elif cmd == "log":
+            logging.info(who)
+          else:
+            logging.info("Invalid Command %s %s" % (cmd,who))
+      self.conn.close()
+      self.socketconn.close()
+    if self.socket:
+      self.socket.shutdown(socket.SHUT_RDWR)
 
 
-fifofile = "/tmp/door_cmd.fifo"
 
-if (not os.path.exists(fifofile)):
-  os.system("mkfifo -m 600 $fifofile")
-  os.system("setfacl -m u:realraum:rw $fifofile")
-  os.system("setfacl -m u:asterisk:rw $fifofile")
-
-logging.info("Door Daemon started")
+fifofile = "/tmp/door_cmd.socket"
 
 arduino = ArduinoUSBThread("/dev/ttyUSB0")
 arduino.start()
 ctrlfifo = ControlFIFOThread(fifofile,arduino)
 ctrlfifo.start()
 
+arduino.send_statusrequest()
+
 def exit_handler(signum, frame):
   global arduino, ctrlfifo
   logging.info("Door Daemon stopping")
@@ -178,6 +209,11 @@ def exit_handler(signum, frame):
   arduino.stop()
   sys.exit(0)
   
-signal.signal(signal.SIGTERM, exit_handler)
+#signals proapbly don't work because of readline
+#signal.signal(signal.SIGTERM, exit_handler)
 signal.signal(signal.SIGINT, exit_handler)
 signal.signal(signal.SIGQUIT, exit_handler)
+
+logging.info("Door Daemon started")
+arduino.join()
+ctrlfifo.join()