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?"
22 syslog.syslog(142, "start check_LAT_service:" + servicename)
24 # Only return after n(retries) consistent results, although not necessarily
25 # in order. This means we poll at least (retries) and up to (retries ** 2) times.
26 # This is mtearle's original code. No idea if it's the Right Thing.
28 syslog.syslog(142, "running c_L_s loop:" + servicename)
30 wfh.write(test_string)
34 syslog.syslog(142, "c_L_s write error:" + servicename)
35 if results['error'] == 0: return -1
37 syslog.syslog(142, "c_Ls written data to " + servicename)
38 rr, wr, er = select([rfh], [], [], 3.0)
41 if results['open'] == 0: return 1
42 syslog.syslog(142, "c_L_s open: " + servicename)
44 syslog.syslog(142, "c_L_s select() succeeded: " + servicename)
45 recv = rfh.read(len(test_string))
46 syslog.syslog(142, "c_L_s read() succeeded: " + servicename)
47 if recv <> test_string:
48 syslog.syslog(142, "c_L_s not the data we sent " + servicename)
50 if results['error'] == 0: return -1
52 results['closed'] -= 1
53 syslog.syslog(142, "c_L_s closed " + servicename)
54 if results['closed'] == 0: return 0
56 class Door(dbus.service.Object):
58 def __init__(self, doorname, bus):
59 self.interval = 10 # seconds
60 self.service = doorname
63 if 'pir' in self.service:
66 # set up D-BUS service name
67 object_path = '/au/asn/ucc/doors/%s' % doorname
68 dbus.service.Object.__init__(self, bus, object_path)
70 # get initial state in a new thread
71 self.timeout = Timer(0, self.poll)
72 # daemon threads will be killed when the mainloop exits
73 # the timeout threads will inherit this value
74 self.timeout.setDaemon(True)
79 newstatus = check_LAT_service(self.service, self.retries)
83 syslog.syslog(142, "status, newstatus for %s is %i, %i" % (self.service, self.status, newstatus))
84 if newstatus != self.status:
85 syslog.syslog(142, "status changed detected for %s" % self.service)
86 self.status = newstatus
88 self.status_changed(newstatus)
90 self.interval = [10,10,20][newstatus]
92 # set up timeout again
93 self.timeout = Timer(self.interval, self.poll)
96 @dbus.service.signal('au.asn.ucc.DoorInterface', signature='n')
97 def status_changed(self, newstatus):
100 @dbus.service.method('au.asn.ucc.DoorInterface', in_signature='',
102 def get_status(self):
105 if __name__ == '__main__':
106 gobject.threads_init()
107 doors = ('uccdoor', 'unisfadoor', 'chdoor', 'mrdoor', 'uccpir')
109 from dbus.mainloop.glib import DBusGMainLoop
110 DBusGMainLoop(set_as_default=True)
112 system_bus = dbus.SystemBus()
113 system_bus.request_name('au.asn.ucc.DoorServer')
118 door_objects.append(Door(door, system_bus))
121 loop = gobject.MainLoop()
124 except KeyboardInterrupt: