add logging of status returned
[uccdoor.git] / server.py
index f0d1336..5f7b571 100755 (executable)
--- a/server.py
+++ b/server.py
@@ -2,12 +2,56 @@
 # UCC Door Server - hardware interface server
 # reads status of reed switches and provides a D-BUS interface to read them
 # David Adam <zanchey@ucc.gu.uwa.edu.au>
+# LAT interface based on work by Mark Tearle <mtearle@ucc.gu.uwa.edu.au>
 # Released under an MIT-style license; see COPYING for details.
 
 # statuses: 1 means open circuit, 0 means closed circuit, -1 means error
 
+import syslog
 import dbus, dbus.service
 import gobject
+from LATClient import LATClient
+from select import select
+from threading import Timer
+
+def check_LAT_service(servicename, retries=3):
+    latclient = LATClient(service=servicename.upper())
+    rfh, wfh = latclient.get_fh()
+    results = {'error': retries, 'closed': retries, 'open': retries}
+    test_string = "got wombles?"
+    syslog.syslog(142, "start check_LAT_service:" + servicename)
+    
+    # Only return after n(retries) consistent results, although not necessarily
+    # in order. This means we poll at least (retries) and up to (retries ** 2) times.
+    # This is mtearle's original code. No idea if it's the Right Thing.
+    while True:
+        syslog.syslog(142, "running c_L_s loop:" + servicename)
+        try:
+            wfh.write(test_string)
+            wfh.flush()
+        except:
+            results['error'] -= 1
+            syslog.syslog(142, "c_L_s write error:" + servicename)
+            if results['error'] == 0: return -1
+            continue
+        syslog.syslog(142, "c_Ls written data to " + servicename)
+        rr, wr, er = select([rfh], [], [], 3.0)
+        if rfh not in rr:
+            results['open'] -= 1
+            if results['open'] == 0: return 1
+            syslog.syslog(142, "c_L_s open: " + servicename)
+            continue
+        syslog.syslog(142, "c_L_s select() succeeded: " + servicename)
+        recv = rfh.read(len(test_string))
+        syslog.syslog(142, "c_L_s read() succeeded: " + servicename)
+        if recv <> test_string:
+            syslog.syslog(142, "c_L_s not the data we sent " + servicename)
+            results['error'] -= 1
+            if results['error'] == 0: return -1
+            continue
+        results['closed'] -= 1
+        syslog.syslog(142, "c_L_s closed " + servicename)
+        if results['closed'] == 0: return 0
 
 class Door(dbus.service.Object):
     
@@ -15,26 +59,41 @@ class Door(dbus.service.Object):
         self.interval = 10 # seconds
         self.service = doorname
         self.status = -1
+        self.retries = 3
+        if 'pir' in self.service:
+            self.retries = 1
         
         # set up D-BUS service name
         object_path = '/au/asn/ucc/doors/%s' % doorname
         dbus.service.Object.__init__(self, bus, object_path)
         
-        # get initial state
-        self.poll()
+        # get initial state in a new thread
+        self.timeout = Timer(0, self.poll)
+        # daemon threads will be killed when the mainloop exits
+        # the timeout threads will inherit this value
+        self.timeout.setDaemon(True)
+        self.timeout.start()
     
     def poll(self):
-        # check LAT
-        # XXX to be added
+        try:
+            newstatus = check_LAT_service(self.service, self.retries)
+        except:
+            newstatus = -1
         
-        newstatus = -1
+        syslog.syslog(142, "status, newstatus for %s is %i, %i" % (servicename, status, newstatus))
         if newstatus != self.status:
+            syslog.syslog(142, "status changed detected for  %s" % servicename)
             self.status = newstatus
             # emit signal
-            # XXX to be added
+            self.status_changed(newstatus)
         
         # set up timeout again
-        gobject.timeout_add_seconds(self.interval, self.poll)
+        self.timeout = Timer(self.interval, self.poll)
+        self.timeout.start()
+    
+    @dbus.service.signal('au.asn.ucc.DoorInterface', signature='n')
+    def status_changed(self, newstatus):
+        pass
     
     @dbus.service.method('au.asn.ucc.DoorInterface', in_signature='',
                          out_signature='n')
@@ -42,6 +101,7 @@ class Door(dbus.service.Object):
         return self.status
 
 if __name__ == '__main__':
+    gobject.threads_init()
     doors = ('uccdoor', 'unisfadoor', 'chdoor', 'mrdoor', 'uccpir')
     
     from dbus.mainloop.glib import DBusGMainLoop

UCC git Repository :: git.ucc.asn.au