X-Git-Url: https://git.ucc.asn.au/?p=uccdoor.git;a=blobdiff_plain;f=server.py;h=5f7b5712446d22715d9e633e82dbd874cb163cce;hp=f0d13369f1c02ed6a206edb3d6fa9611f758da69;hb=5e211c6460db7dd20b77d147eca5a15a0df41a4b;hpb=446ae2bd2f559e56ffc35ada410f55dabb7d996c diff --git a/server.py b/server.py index f0d1336..5f7b571 100755 --- 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 +# LAT interface based on work by Mark Tearle # 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