class ZigBee(object): def __init__(self, serial_port, baud_rate, dispatcher, serializer): self.ser = serial.Serial(serial_port, baud_rate) self.zb = xbee.ZigBee(self.ser, escaped=True) self.dispatch = Dispatch(xbee=self.zb) self.dispatch.register('rx', self.rx_handler, lambda p: p['id'] == 'rx') self.dispatch.register('rx_explicit', self.default_handler, lambda p: p['id'] == 'rx_explicit') self.dispatch.register('rx_io_data_long_addr', self.default_handler, lambda p: p['id'] == 'rx_io_data_long_addr') self.dispatch.register('tx_status', self.default_handler, lambda p: p['id'] == 'tx_status') self.dispatch.register('status', self.default_handler, lambda p: p['id'] == 'status') self.dispatch.register('at_response', self.at_response_handler, lambda p: p['id'] == 'at_response') self.dispatch.register('remote_at_response', self.default_handler, lambda p: p['id'] == 'remote_at_response') self.dispatch.register('node_id_indicator', self.default_handler, lambda p: p['id'] == 'node_id_indicator') self.dispatcher = dispatcher self.serializer = serializer def default_handler(self, name, packet): print "%s - %s" % (name, packet) def at_response_handler(self, name, packet): p = ''.join('%02x' % ord(x) for x in packet['parameter']) print "AT - %s = %s" % (packet['command'], p) def rx_handler(self, name, packet): req = self.serializer.deserialize_request(packet['rf_data']) if not req: print "Ignoring garbage request" return rsp = self.dispatcher.dispatch(req) data = self.serializer.serialize_response(rsp) dst_long = packet['source_addr_long'] dst_addr = packet['source_addr'] print packet self.zb.tx(dest_addr_long=dst_long, dest_addr=dst_addr, data=data) def run(self): try: print "Run!" self.dispatch.run() except KeyboardInterrupt: pass print "Bye!" self.ser.close()
class ZigBee(object): def __init__(self, serial_port, baud_rate, dispatcher, serializer): self.ser = serial.Serial(serial_port, baud_rate) self.zb = xbee.ZigBee(self.ser, escaped=True) self.dispatch = Dispatch(xbee = self.zb) self.dispatch.register('rx', self.rx_handler, lambda p: p['id'] == 'rx') self.dispatch.register('rx_explicit', self.default_handler, lambda p: p['id'] == 'rx_explicit') self.dispatch.register('rx_io_data_long_addr', self.default_handler, lambda p: p['id'] == 'rx_io_data_long_addr') self.dispatch.register('tx_status', self.default_handler, lambda p: p['id'] == 'tx_status') self.dispatch.register('status', self.default_handler, lambda p: p['id'] == 'status') self.dispatch.register('at_response', self.at_response_handler, lambda p: p['id'] == 'at_response') self.dispatch.register('remote_at_response', self.default_handler, lambda p: p['id'] == 'remote_at_response') self.dispatch.register('node_id_indicator', self.default_handler, lambda p: p['id'] == 'node_id_indicator') self.dispatcher = dispatcher self.serializer = serializer def default_handler(self, name, packet): print "%s - %s" % (name, packet) def at_response_handler(self, name, packet): p = ''.join('%02x' % ord(x) for x in packet['parameter']) print "AT - %s = %s" % (packet['command'], p) def rx_handler(self, name, packet): req = self.serializer.deserialize_request(packet['rf_data']) if not req: print "Ignoring garbage request" return rsp = self.dispatcher.dispatch(req) data = self.serializer.serialize_response(rsp) dst_long = packet['source_addr_long'] dst_addr = packet['source_addr'] print packet self.zb.tx(dest_addr_long=dst_long, dest_addr=dst_addr, data=data) def run(self): try: print "Run!" self.dispatch.run() except KeyboardInterrupt: pass print "Bye!" self.ser.close()
class TestDispatch(unittest.TestCase): """ Tests xbee.helpers.dispatch for expected behavior """ def setUp(self): self.xbee = FakeXBee(None) self.dispatch = Dispatch(xbee=self.xbee) self.callback_check = CallbackCheck() def test_callback_is_called_when_registered(self): """ After registerring a callback function with a filter function, the callback should be called when data arrives. """ self.dispatch.register("test1", self.callback_check.call, lambda data: True) self.dispatch.run(oneshot=True) self.assertTrue(self.callback_check.called) def test_callback_not_called_when_filter_not_satisfied(self): """ After registerring a callback function with a filter function, the callback should not be called if a packet which does not satisfy the callback's filter arrives. """ self.dispatch.register("test1", self.callback_check.call, lambda data: False) self.dispatch.run(oneshot=True) self.assertFalse(self.callback_check.called) def test_multiple_callbacks(self): """ Many callbacks should be called on the same packet if each callback's filter method is satisfied. """ callbacks = [] for i in range(0, 10): check = CallbackCheck() callbacks.append(check) self.dispatch.register("test%d" % i, check.call, lambda data: True) self.dispatch.run(oneshot=True) for callback in callbacks: if not callback.called: self.fail("All callback methods should be called") def test_callback_name_collisions_raise_valueerror(self): """ If a call to register() results in attempting to register a callback with the same name as another callback should result in a ValueError exception being raised. """ self.dispatch.register("test", None, None) self.assertRaises(ValueError, self.dispatch.register, "test", None, None)
# Functionally, these are the same. dispatch = Dispatch(ser) # Register the packet handlers with the dispatch: # The string name allows one to distinguish between mutiple registrations # for a single callback function # The second argument is the function to call # The third argument is a function which determines whether to call its # associated callback when a packet arrives. It should return a boolean. dispatch.register( "status", status_handler, lambda packet: packet['id']=='status' ) dispatch.register( "io_data", io_sample_handler, lambda packet: packet['id']=='rx_io_data' ) try: # run() will loop infinitely while waiting for and processing # packets which arrive. Don't expect it to return (unless an # exception occurs). dispatch.run() except KeyboardInterrupt: pass ser.close()
# create an XBee object on your behalf for accessing the device. # If you wish, you may explicitly provide your own XBee: # # xbee = XBee(ser) # dispatch = Dispatch(xbee=xbee) # # Functionally, these are the same. dispatch = Dispatch(ser) # Register the packet handlers with the dispatch: # The string name allows one to distinguish between mutiple registrations # for a single callback function # The second argument is the function to call # The third argument is a function which determines whether to call its # associated callback when a packet arrives. It should return a boolean. dispatch.register("status", status_handler, lambda packet: packet['id'] == 'status') dispatch.register("io_data", io_sample_handler, lambda packet: packet['id'] == 'rx_io_data') try: # run() will loop infinitely while waiting for and processing # packets which arrive. Don't expect it to return (unless an # exception occurs). dispatch.run() except KeyboardInterrupt: pass ser.close()