async def test_broadcast_display(uhs500_msg_bytes, uhs500_msg_parsed, udp_endpoint, udp_port, faker): transport, protocol, endpoint_port = udp_endpoint assert udp_port != endpoint_port loop = asyncio.get_event_loop() receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) displays_by_index = { disp.index: disp for disp in uhs500_msg_parsed.displays } async with receiver: # Populate the receiver's tallies and wait for them to be added transport.sendto(uhs500_msg_bytes, ('127.0.0.1', udp_port)) _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() assert len(receiver.tallies) == len(uhs500_msg_parsed.displays) receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) # Send a broadcast display message for each TallyColor with a random brightness # The control field is set so the Tally text field is unchanged for color in TallyColor: brightness = faker.pyint(max_value=3) bc_disp = Display.broadcast( control=b'foo', rh_tally=color, lh_tally=color, txt_tally=color, brightness=brightness, ) msg = Message(displays=[bc_disp]) transport.sendto(msg.build_message(), ('127.0.0.1', udp_port)) _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() # Check each of the receiver's tallies against the bc_disp values # and make sure the text didn't change for tally in receiver.tallies.values(): assert tally.index < 0xffff assert not tally.is_broadcast assert tally.rh_tally == color assert tally.txt_tally == color assert tally.lh_tally == color assert tally.control == bc_disp.control assert tally.brightness == brightness assert tally.text == displays_by_index[tally.index].text
async def test_rebind(uhs500_msg_bytes, uhs500_msg_parsed, udp_endpoint, udp_port, unused_tcp_port_factory): transport, protocol, endpoint_port = udp_endpoint assert udp_port != endpoint_port loop = asyncio.get_event_loop() receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) async with receiver: # Send message bytes to receiver and wait for ``on_tally_added`` events transport.sendto(uhs500_msg_bytes, ('127.0.0.1', udp_port)) _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() assert len(receiver.tallies) == len(uhs500_msg_parsed.displays) # Set up to get ``on_tally_updated`` callbacks receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) # Change bind address and trigger a change await receiver.set_hostaddr('0.0.0.0') assert receiver.hostaddr == '0.0.0.0' disp = uhs500_msg_parsed.displays[0] disp.brightness = 1 transport.sendto(uhs500_msg_parsed.build_message(), ('0.0.0.0', udp_port)) evt_args, evt_kwargs = await evt_listener.get() evt_tally = evt_args[0] assert disp == evt_tally # Change bind port and trigger a change new_port = unused_tcp_port_factory() assert new_port != udp_port await receiver.set_hostport(new_port) assert receiver.hostport == new_port disp.brightness = 2 transport.sendto(uhs500_msg_parsed.build_message(), ('0.0.0.0', new_port)) evt_args, evt_kwargs = await evt_listener.get() evt_tally = evt_args[0] assert disp == evt_tally
async def test_parse_errors(faker, udp_endpoint, udp_port): transport, protocol, endpoint_port = udp_endpoint assert udp_port != endpoint_port loop = asyncio.get_event_loop() receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) msgobj = Message() disp = Display(index=0, text='foo') msgobj.displays.append(disp) async with receiver: transport.sendto(msgobj.build_message(), ('127.0.0.1', udp_port)) _ = await evt_listener.get() receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) screen = receiver.screens[msgobj.screen] rx_disp = screen[disp.index] assert rx_disp is receiver.tallies[rx_disp.id] assert rx_disp == disp for i in range(100): num_bytes = faker.pyint(min_value=1, max_value=1024) bad_bytes = faker.binary(length=num_bytes) with pytest.raises(ParseError): receiver.parse_incoming(bad_bytes, ('127.0.0.1', endpoint_port)) transport.sendto(bad_bytes, ('127.0.0.1', udp_port)) disp.text = f'foo_{i}' transport.sendto(msgobj.build_message(), ('127.0.0.1', udp_port)) _ = await evt_listener.get() assert rx_disp == disp
async def test_with_uhs_data(uhs500_msg_bytes, uhs500_msg_parsed, udp_endpoint, udp_port): transport, protocol, endpoint_port = udp_endpoint assert udp_port != endpoint_port loop = asyncio.get_event_loop() receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) uhs_screen = uhs500_msg_parsed.screen async with receiver: # Send message bytes to receiver transport.sendto(uhs500_msg_bytes, ('127.0.0.1', udp_port)) # Wait for all ``on_tally_added`` events _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() screen = receiver.screens[uhs_screen] # Check all receiver tallies against the expected ones assert len(receiver.tallies) == len(uhs500_msg_parsed.displays) for disp in uhs500_msg_parsed.displays: assert disp.index in screen tally = screen.tallies[disp.index] assert tally.id == (uhs_screen, disp.index) assert receiver.tallies[tally.id] is tally assert disp == tally # Change each display and send the updated message to receiver # Then wait for ``on_tally_updated`` events receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) for disp in uhs500_msg_parsed.displays: tally = screen.tallies[disp.index] for tally_type in TallyType.all(): attr = tally_type.name cur_value = getattr(disp, attr) if cur_value == TallyColor.RED: new_value = TallyColor.GREEN else: new_value = TallyColor.RED setattr(disp, attr, new_value) disp.text = f'{disp.text}-foo' disp.brightness = 1 transport.sendto(uhs500_msg_parsed.build_message(), ('127.0.0.1', udp_port)) evt_args, evt_kwargs = await evt_listener.get() evt_tally = evt_args[0] assert evt_tally is tally assert disp == tally
async def test_with_uhs_data(udp_port): loop = asyncio.get_event_loop() sender = UmdSender(clients=[('127.0.0.1', udp_port)]) receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) screen_index = 1 async with receiver: async with sender: # Create initial tallies using text method for i in range(100): t_id = (screen_index, i) sender.set_tally_text(t_id, f'Tally-{i}') tx_tally = sender.tallies[t_id] screen = sender.screens[screen_index] assert screen[i] is tx_tally evt_args, evt_kwargs = await evt_listener.get() rx_tally = evt_args[0] assert rx_tally == tx_tally # Create one more tally using ``set_tally_color`` t_id = (screen_index, 200) sender.set_tally_color(t_id, TallyType.lh_tally, TallyColor.GREEN) tx_tally = sender.tallies[t_id] assert screen[200] is tx_tally evt_args, evt_kwargs = await evt_listener.get() rx_tally = evt_args[0] assert rx_tally == tx_tally # Allow the sender to do a full refresh. Nothing should have changed await asyncio.sleep(sender.tx_interval) assert evt_listener.empty() # Connect to ``on_tally_updated`` events receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) # Change each tally/tally_type color to red and check the received values for tx_tally in sender.tallies.values(): for tally_type in TallyType.all(): sender.set_tally_color(tx_tally.id, tally_type, TallyColor.RED) evt_args, evt_kwargs = await evt_listener.get() rx_tally = evt_args[0] assert rx_tally is receiver.tallies[tx_tally.id] assert rx_tally == tx_tally # Change the text of the extra tally from above and check t_id = (screen_index, 200) sender.set_tally_text(t_id, 'Tally-200') tx_tally = sender.tallies[t_id] evt_args, evt_kwargs = await evt_listener.get() rx_tally = evt_args[0] assert rx_tally == tx_tally # Let the sender to another full refresh await asyncio.sleep(sender.tx_interval) assert evt_listener.empty() # Change all tally/tally_type colors, but don't wait for results yet for tx_tally in sender.tallies.values(): for tally_type in TallyType.all(): sender.set_tally_color(tx_tally.id, tally_type, TallyColor.AMBER) sender.set_tally_text(tx_tally.id, f'foo-{tx_tally.index}') # Wait for updates from last loop to get to the receiver # and check the results _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() for tx_tally in sender.tallies.values(): rx_tally = receiver.tallies[tx_tally.id] assert rx_tally == tx_tally
async def test_broadcast_display(udp_port): loop = asyncio.get_event_loop() sender = UmdSender(clients=[('127.0.0.1', udp_port)]) receiver = UmdReceiver(hostaddr='127.0.0.1', hostport=udp_port) evt_listener = EventListener() receiver.bind_async(loop, on_tally_added=evt_listener.callback) async def wait_for_receiver(): _ = await evt_listener.get() while not evt_listener.empty(): _ = await evt_listener.get() await asyncio.sleep(sender.tx_interval) assert evt_listener.empty() color_kw = { attr: TallyColor.RED for attr in ['rh_tally', 'txt_tally', 'lh_tally'] } screen_index = 1 async with receiver: async with sender: # Create initial tallies for i in range(10): t_id = (screen_index, i) tx_tally = sender.add_tally(t_id, **color_kw) screen = sender.screens[screen_index] assert screen[i] is tx_tally tx_tally.text = f'Tally-{i}' evt_args, evt_kwargs = await evt_listener.get() rx_tally = evt_args[0] assert rx_tally == tx_tally # Connect to ``on_tally_updated`` events receiver.unbind(evt_listener) receiver.bind_async(loop, on_tally_updated=evt_listener.callback) # Send a broadcast tally for each color setting all TallyType's to it for color in TallyColor: color_kw = {k: color for k in color_kw.keys()} await sender.send_broadcast_tally(screen_index, **color_kw) await wait_for_receiver() # Check the tally colors and make sure the text values remained for rx_tally in receiver.tallies.values(): tx_tally = sender.tallies[rx_tally.id] assert rx_tally.text == tx_tally.text == f'Tally-{rx_tally.index}' assert rx_tally.rh_tally == tx_tally.rh_tally == color assert rx_tally.txt_tally == tx_tally.txt_tally == color assert rx_tally.lh_tally == tx_tally.lh_tally == color # Broadcast all colors to "OFF" and set all names to 'foo' color_kw = {k: TallyColor.OFF for k in color_kw.keys()} await sender.send_broadcast_tally(screen_index, text='foo', **color_kw) await wait_for_receiver() # Check the tally colors and text values for rx_tally in receiver.tallies.values(): tx_tally = sender.tallies[rx_tally.id] assert rx_tally.text == tx_tally.text == 'foo' assert rx_tally.rh_tally == tx_tally.rh_tally == TallyColor.OFF assert rx_tally.txt_tally == tx_tally.txt_tally == TallyColor.OFF assert rx_tally.lh_tally == tx_tally.lh_tally == TallyColor.OFF # Send broadcast tally control messages for control_data in [b'foo', b'bar', b'baz']: await sender.send_broadcast_tally(screen_index, control=control_data) await wait_for_receiver() # Check for the correct control data and ensure other values # remain unchanged for rx_tally in receiver.tallies.values(): tx_tally = sender.tallies[rx_tally.id] assert rx_tally.control == tx_tally.control == control_data assert rx_tally.text == tx_tally.text == 'foo' assert rx_tally.rh_tally == tx_tally.rh_tally == TallyColor.OFF assert rx_tally.txt_tally == tx_tally.txt_tally == TallyColor.OFF assert rx_tally.lh_tally == tx_tally.lh_tally == TallyColor.OFF # Do the same as above, but using the `sender.send_broadcast_tally_control` method # and change one tally color for control_data in [b'abc', b'def', b'ghi']: await sender.send_broadcast_tally_control( screen_index, control_data, rh_tally=TallyColor.RED) await wait_for_receiver() # Check for the correct control data and ensure other values for rx_tally in receiver.tallies.values(): tx_tally = sender.tallies[rx_tally.id] assert rx_tally.control == tx_tally.control == control_data assert rx_tally.text == tx_tally.text == 'foo' assert rx_tally.rh_tally == tx_tally.rh_tally == TallyColor.RED assert rx_tally.txt_tally == tx_tally.txt_tally == TallyColor.OFF assert rx_tally.lh_tally == tx_tally.lh_tally == TallyColor.OFF