def _update_clock(self, event: ReceiveEvent) -> None: """Handle any clock update.""" if event.time is not None: self.current_time = event.time self._mcu_state_synchronizer.input( states.UpdateEvent(time=self.current_time)) self._frontend_state_synchronizer.input( states.UpdateEvent(time=self.current_time)) self._file_state_synchronizer.input( states.UpdateEvent(time=self.current_time))
def test_sync_outputs_multitype() -> None: """Test multi-type output scheduling from input sequences.""" synchronizer = states.Synchronizer(message_classes=mcu.MESSAGE_CLASSES, output_schedule=collections.deque([ states.ScheduleEntry(time=0.1, type=pb.Ping), states.ScheduleEntry( time=0.9, type=pb.Announcement), ])) # schedule has not yet started assert synchronizer.output_schedule[0].time == 0.1 assert synchronizer.output_deadline is None assert synchronizer.output() is None # schedule entry 1 synchronizer.input(states.UpdateEvent(time=0, pb_message=pb.Ping(id=1))) synchronizer.input( states.UpdateEvent(pb_message=pb.Announcement(announcement=b'1'))) assert synchronizer.current_time == 0 assert synchronizer.output_schedule[0].time == 0.1 assert synchronizer.output_deadline == 0.1 assert synchronizer.all_states[pb.Ping] == pb.Ping(id=1) assert synchronizer.all_states[pb.Announcement] == pb.Announcement( announcement=b'1') update_clock(synchronizer, 0.05) assert synchronizer.output() is None update_clock(synchronizer, 0.1) assert synchronizer.output() == pb.Ping(id=1) # schedule entry 2 assert synchronizer.output_schedule[0].time == 0.9 assert synchronizer.output_deadline == 1.0 update_clock(synchronizer, 0.5) assert synchronizer.output() is None synchronizer.input(states.UpdateEvent(pb_message=pb.Ping(id=2))) assert synchronizer.all_states[pb.Ping] == pb.Ping(id=2) update_clock(synchronizer, 1.0) assert synchronizer.output() == pb.Announcement(announcement=b'1') # schedule entry 1 assert synchronizer.output_schedule[0].time == 0.1 assert synchronizer.output_deadline == 1.1 update_clock(synchronizer, 1.05) assert synchronizer.output() is None update_clock(synchronizer, 1.1) assert synchronizer.output() == pb.Ping(id=2) # schedule entry 2 assert synchronizer.output_schedule[0].time == 0.9 assert synchronizer.output_deadline == 2.0 assert synchronizer.output() is None update_clock(synchronizer, 2.0) assert synchronizer.output() == pb.Announcement(announcement=b'1')
def _handle_mcu_inbound_state(self, event: ReceiveEvent) -> None: """Handle any inbound state update from the MCU.""" if (event.mcu_receive is None or type(event.mcu_receive) not in self.MCU_INPUT_TYPES): return try: self._mcu_state_synchronizer.input( states.UpdateEvent(pb_message=event.mcu_receive)) except exceptions.ProtocolDataError: self._logger.exception('MCU State Synchronizer: %s', event.mcu_receive) try: self._file_state_synchronizer.input( states.UpdateEvent(pb_message=event.mcu_receive)) except exceptions.ProtocolDataError: self._logger.exception('File Save State Synchronizer Save: %s', event.mcu_receive)
def _handle_frontend_inbound_state(self, event: ReceiveEvent) -> None: """Handle any inbound state update from the frontend.""" if (event.frontend_receive is None or type(event.frontend_receive) not in self.FRONTEND_INPUT_TYPES): return try: self._frontend_state_synchronizer.input( states.UpdateEvent(pb_message=event.frontend_receive)) except exceptions.ProtocolDataError: self._logger.exception('Frontend State Synchronizer: %s', event.frontend_receive)
def test_sync_inputs() -> None: """Test state updating from input sequences.""" example_sequence = [(pb.Ping, states.UpdateEvent(time=i, pb_message=pb.Ping(id=i))) for i in range(8)] synchronizer = states.Synchronizer(message_classes=mcu.MESSAGE_CLASSES, output_schedule=collections.deque([ states.ScheduleEntry(time=1.0, type=pb.Ping) ])) assert synchronizer.output() is None for (message_type, update_event) in example_sequence: synchronizer.input(update_event) assert synchronizer.current_time == update_event.time assert synchronizer.all_states[message_type] == update_event.pb_message
def test_sync_outputs_singletype() -> None: """Test single-type output scheduling from input sequences.""" synchronizer = states.Synchronizer(message_classes=mcu.MESSAGE_CLASSES, output_schedule=collections.deque([ states.ScheduleEntry(time=1.0, type=pb.Ping), states.ScheduleEntry(time=2.0, type=pb.Ping), states.ScheduleEntry(time=3.0, type=pb.Ping), ])) # schedule has not yet started assert synchronizer.output_schedule[0].time == 1.0 assert synchronizer.output_deadline is None assert synchronizer.output() is None assert synchronizer.output_schedule[0].time == 1.0 assert synchronizer.output_deadline is None # schedule entry 1 synchronizer.input(states.UpdateEvent(time=0, pb_message=pb.Ping(id=1))) assert synchronizer.current_time == 0 assert synchronizer.output_schedule[0].time == 1.0 assert synchronizer.output_deadline == 1.0 assert synchronizer.all_states[pb.Ping] == pb.Ping(id=1) update_clock(synchronizer, 0.9) assert synchronizer.output() is None update_clock(synchronizer, 1.0) assert synchronizer.output() == pb.Ping(id=1) assert synchronizer.output() is None assert synchronizer.all_states[pb.Ping] == pb.Ping(id=1) # schedule entry 2 assert synchronizer.output_schedule[0].time == 2.0 assert synchronizer.output_deadline == 3.0 update_clock(synchronizer, 1.5) assert synchronizer.output() is None synchronizer.input(states.UpdateEvent(pb_message=pb.Ping(id=2))) assert synchronizer.all_states[pb.Ping] == pb.Ping(id=2) update_clock(synchronizer, 3.0) assert synchronizer.output() == pb.Ping(id=2) assert synchronizer.output() is None assert synchronizer.all_states[pb.Ping] == pb.Ping(id=2) # schedule entry 3 assert synchronizer.output_schedule[0].time == 3.0 assert synchronizer.output_deadline == 6.0 update_clock(synchronizer, 4.0) assert synchronizer.output() is None synchronizer.input(states.UpdateEvent(pb_message=pb.Ping(id=3))) assert synchronizer.all_states[pb.Ping] == pb.Ping(id=3) update_clock(synchronizer, 5.0) assert synchronizer.output() is None synchronizer.input(states.UpdateEvent(pb_message=pb.Ping(id=4))) assert synchronizer.all_states[pb.Ping] == pb.Ping(id=4) update_clock(synchronizer, 6.0) assert synchronizer.output() == pb.Ping(id=4) assert synchronizer.output() is None assert synchronizer.all_states[pb.Ping] == pb.Ping(id=4) # schedule entry 1 assert synchronizer.output_schedule[0].time == 1.0 assert synchronizer.output_deadline == 7.0 synchronizer.input(states.UpdateEvent(pb_message=pb.Ping(id=5))) assert synchronizer.output() is None update_clock(synchronizer, 7.0) assert synchronizer.output() == pb.Ping(id=5) assert synchronizer.output() is None assert synchronizer.all_states[pb.Ping] == pb.Ping(id=5)
def update_clock(synchronizer: states.Synchronizer, time: float) -> None: """Update the clock of the synchronizer.""" synchronizer.input(states.UpdateEvent(time=time))