class OSCComunication: target_ip = "" ping_num = 0 ping_rate = 2 server = None client = None def __init__(self, host_ip, in_port=3821): self.in_port = in_port self.host_ip = host_ip self.running = False self.message_queue = [] self.last_ping_time = datetime.min self._setup_server() self.connected = False def close(self): self._send_exit() self.transport.close() def queue_messages(self, msgs): for (address, msg) in msgs: self.queue_message(address, msg) def queue_message(self, address, msg): if (self.client != None): self.message_queue.insert(0, (address, msg)) async def send_queue(self): for (address, msg) in self.message_queue: self.send(address, msg) await asyncio.sleep(0) self.message_queue = [] async def main_loop(self): self.running = True asyncio.ensure_future(self.ping_loop()) while (self.running): await self.send_queue() await asyncio.sleep(0) if ((self.last_ping_time - datetime.now()).seconds > 10 and self.connected): self.connected = False self.dispatcher.map("/handshake/", self._handshake_handler) async def ping_loop(self): while (True): if (self.client != None): self._send_ping() await asyncio.sleep(self.ping_rate) def send(self, address, args): if (self.client == None): return #print(address) #print(args) self.client.send_message(address, args) def _send_ping(self): self.send("/ping/", [self.ping_num]) self.ping_num = self.ping_num + 1 def _send_exit(self): self.send("/exit/", [True]) def _setup_sender(self): print("Setting up client {}, {}".format(self.target_ip, self.out_port)) self.client = SimpleUDPClient(self.target_ip, self.out_port) def _setup_server(self): print("Setting up server {}, {}".format(self.host_ip, self.in_port)) self.dispatcher = Dispatcher() self.dispatcher.map("/handshake/", self._handshake_handler) self.dispatcher.map("/ping/", self._ping_handler) self.dispatcher.map("/start/", self._start_handler) self.dispatcher.map("/stop/", self._stop_handler) self.server = AsyncIOOSCUDPServer((self.host_ip, self.in_port), self.dispatcher, asyncio.get_event_loop()) async def start_server(self): self.transport, self.protocol = await self.server.create_serve_endpoint( ) # Create datagram endpoint and start serving return def _handshake_handler(self, address, osc_arguments): if (self.target_ip != ""): return self.target_ip = "192.168.0.199" self.out_port = osc_arguments print("Handshake received. IP: {} PORT: {}".format( self.target_ip, self.out_port)) self.dispatcher.unmap("/handshake/", self._handshake_handler) self._setup_sender() self.connected = True def _ping_handler(self, address, osc_arguments): self.last_ping_time = datetime.now() pass def _start_handler(self, address, osc_arguments): pass def _stop_handler(self, address, osc_arguments): pass
class TestDispatcher(unittest.TestCase): def setUp(self): super().setUp() self.dispatcher = Dispatcher() def sortAndAssertSequenceEqual(self, expected, result): def sort(lst): return sorted(lst, key=lambda x: x.callback) return self.assertSequenceEqual(sort(expected), sort(result)) def test_empty_by_default(self): self.sortAndAssertSequenceEqual([], self.dispatcher.handlers_for_address('/test')) def test_use_default_handler_when_set_and_no_match(self): handler = object() self.dispatcher.set_default_handler(handler) self.sortAndAssertSequenceEqual([Handler(handler, [])], self.dispatcher.handlers_for_address('/test')) def test_simple_map_and_match(self): handler = object() self.dispatcher.map('/test', handler, 1, 2, 3) self.dispatcher.map('/test2', handler) self.sortAndAssertSequenceEqual( [Handler(handler, [1, 2, 3])], self.dispatcher.handlers_for_address('/test')) self.sortAndAssertSequenceEqual( [Handler(handler, [])], self.dispatcher.handlers_for_address('/test2')) def test_example_from_spec(self): addresses = [ "/first/this/one", "/second/1", "/second/2", "/third/a", "/third/b", "/third/c", ] for index, address in enumerate(addresses): self.dispatcher.map(address, index) for index, address in enumerate(addresses): self.sortAndAssertSequenceEqual( [Handler(index, [])], self.dispatcher.handlers_for_address(address)) self.sortAndAssertSequenceEqual( [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/second/?")) self.sortAndAssertSequenceEqual( [Handler(3, []), Handler(4, []), Handler(5, [])], self.dispatcher.handlers_for_address("/third/*")) def test_do_not_match_over_slash(self): self.dispatcher.map('/foo/bar/1', 1) self.dispatcher.map('/foo/bar/2', 2) self.sortAndAssertSequenceEqual( [], self.dispatcher.handlers_for_address("/*")) def test_match_middle_star(self): self.dispatcher.map('/foo/bar/1', 1) self.dispatcher.map('/foo/bar/2', 2) self.sortAndAssertSequenceEqual( [Handler(2, [])], self.dispatcher.handlers_for_address("/foo/*/2")) def test_match_multiple_stars(self): self.dispatcher.map('/foo/bar/1', 1) self.dispatcher.map('/foo/bar/2', 2) self.sortAndAssertSequenceEqual( [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/*/*/*")) def test_match_address_contains_plus_as_character(self): self.dispatcher.map('/footest/bar+tender/1', 1) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address("/foo*/bar+*/*")) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address("/foo*/bar*/*")) def test_call_correct_dispatcher_on_star(self): self.dispatcher.map('/a+b', 1) self.dispatcher.map('/aaab', 2) self.sortAndAssertSequenceEqual( [Handler(2, [])], self.dispatcher.handlers_for_address('/aaab')) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address('/a+b')) def test_map_star(self): self.dispatcher.map('/starbase/*', 1) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address("/starbase/bar")) def test_map_root_star(self): self.dispatcher.map('/*', 1) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address("/anything/matches")) def test_map_double_stars(self): self.dispatcher.map('/foo/*/bar/*', 1) self.sortAndAssertSequenceEqual( [Handler(1, [])], self.dispatcher.handlers_for_address("/foo/wild/bar/wild")) self.sortAndAssertSequenceEqual( [], self.dispatcher.handlers_for_address("/foo/wild/nomatch/wild")) def test_multiple_handlers(self): self.dispatcher.map('/foo/bar', 1) self.dispatcher.map('/foo/bar', 2) self.sortAndAssertSequenceEqual( [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/foo/bar")) def test_multiple_handlers_with_wildcard_map(self): self.dispatcher.map('/foo/bar', 1) self.dispatcher.map('/*', 2) self.sortAndAssertSequenceEqual( [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/foo/bar")) def test_unmap(self): def dummyhandler(): pass # Test with handler returned by map returnedhandler = self.dispatcher.map("/map/me", dummyhandler) self.sortAndAssertSequenceEqual([Handler(dummyhandler, [])], self.dispatcher.handlers_for_address("/map/me")) self.dispatcher.unmap("/map/me", returnedhandler) self.sortAndAssertSequenceEqual([], self.dispatcher.handlers_for_address("/map/me")) # Test with reconstructing handler self.dispatcher.map("/map/me/too", dummyhandler) self.sortAndAssertSequenceEqual([Handler(dummyhandler, [])], self.dispatcher.handlers_for_address("/map/me/too")) self.dispatcher.unmap("/map/me/too", dummyhandler) self.sortAndAssertSequenceEqual([], self.dispatcher.handlers_for_address("/map/me/too")) def test_unmap_exception(self): def dummyhandler(): pass with self.assertRaises(ValueError) as context: self.dispatcher.unmap("/unmap/exception", dummyhandler) handlerobj = self.dispatcher.map("/unmap/somethingelse", dummyhandler()) with self.assertRaises(ValueError) as context: self.dispatcher.unmap("/unmap/exception", handlerobj)