2 # UCC Door Server - hardware interface server
3 # reads status of reed switches and provides a D-BUS interface to read them
6 # Released under an MIT-style license; see COPYING for details.
8 # statuses: 1 means open circuit, 0 means closed circuit, -1 means error
11 import dbus, dbus.service
13 from LATClient import LATClient
14 from select import select
15 from threading import Timer
17 def check_LAT_service(servicename, retries=3):
18 latclient = LATClient(service=servicename.upper())
19 rfh, wfh = latclient.get_fh()
20 results = {'error': retries, 'closed': retries, 'open': retries}
21 test_string = "got wombles?"
23 # Only return after n(retries) consistent results, although not necessarily
24 # in order. This means we poll at least (retries) and up to (retries ** 2) times.
25 # This is mtearle's original code. No idea if it's the Right Thing.
28 wfh.write(test_string)
32 if results['error'] == 0: return -1
34 rr, wr, er = select([rfh], [], [], 3.0)
37 if results['open'] == 0: return 1
39 recv = rfh.read(len(test_string))
40 if recv <> test_string:
42 if results['error'] == 0: return -1
44 results['closed'] -= 1
45 if results['closed'] == 0: return 0
47 class Door(dbus.service.Object):
49 def __init__(self, doorname, bus):
50 self.interval = 10 # seconds
51 self.service = doorname
54 if 'pir' in self.service:
57 # set up D-BUS service name
58 object_path = '/au/asn/ucc/doors/%s' % doorname
59 dbus.service.Object.__init__(self, bus, object_path)
61 # get initial state in a new thread
62 self.timeout = Timer(0, self.poll)
63 # daemon threads will be killed when the mainloop exits
64 # the timeout threads will inherit this value
65 self.timeout.setDaemon(True)
70 newstatus = check_LAT_service(self.service, self.retries)
74 if newstatus != self.status:
75 syslog.syslog(142, "status changed detected for %s; status: %i, newstatus: %i" % (self.service, self.status, newstatus))
76 self.status = newstatus
78 self.status_changed(newstatus)
80 self.interval = [10,10,30][newstatus]
82 # set up timeout again
83 self.timeout = Timer(self.interval, self.poll)
86 @dbus.service.signal('au.asn.ucc.DoorInterface', signature='n')
87 def status_changed(self, newstatus):
90 @dbus.service.method('au.asn.ucc.DoorInterface', in_signature='',
95 if __name__ == '__main__':
96 gobject.threads_init()
97 doors = ('uccdoor', 'unisfadoor', 'chdoor', 'mrdoor', 'uccpir')
99 from dbus.mainloop.glib import DBusGMainLoop
100 DBusGMainLoop(set_as_default=True)
102 system_bus = dbus.SystemBus()
103 system_bus.request_name('au.asn.ucc.DoorServer')
108 door_objects.append(Door(door, system_bus))
111 loop = gobject.MainLoop()
114 except KeyboardInterrupt: