def test_master_output_event(self): events = [] def _on_event(master_event): events.append(master_event) classic = get_classic_controller_dummy() pubsub = get_pubsub() pubsub.subscribe_master_events(PubSub.MasterTopics.OUTPUT, _on_event) classic._output_config = { 0: OutputDTO(id=0), 1: OutputDTO(id=1), 2: OutputDTO(id=2, room=3) } pubsub._publish_all_events() events = [] classic._on_master_output_event({'outputs': [(0, 0), (2, 5)]}) pubsub._publish_all_events() assert [ MasterEvent('OUTPUT_STATUS', { 'id': 0, 'status': True, 'dimmer': 0 }), MasterEvent('OUTPUT_STATUS', { 'id': 1, 'status': False }), MasterEvent('OUTPUT_STATUS', { 'id': 2, 'status': True, 'dimmer': 5 }) ] == events
def test_update(self): _ = self cache = OutputStateCache() cache.update_outputs( [OutputDTO(id=0), OutputDTO(id=1), OutputDTO(id=2)]) current_state = cache.get_state() assert { 0: OutputStateDTO(id=0), 1: OutputStateDTO(id=1), 2: OutputStateDTO(id=2) } == current_state # Everything is off. assert cache.handle_change(OutputStateDTO(0, status=False))[0] is False assert cache.handle_change(OutputStateDTO(1, status=False))[0] is False assert cache.handle_change(OutputStateDTO(2, status=False))[0] is False # Turn two outputs on. assert cache.handle_change(OutputStateDTO(0, status=False))[0] is False changed, output_dto = cache.handle_change( OutputStateDTO(2, status=True)) assert output_dto.state.status is True assert changed is True changed, output_dto = cache.handle_change( OutputStateDTO(1, status=True)) assert output_dto.state.status is True assert changed is True # Turn one outputs off again. assert cache.handle_change(OutputStateDTO(0, status=False))[0] is False changed, output_dto = cache.handle_change( OutputStateDTO(1, status=False)) assert output_dto.state.status is False assert changed is True # Change dimmer value. assert cache.handle_change(OutputStateDTO(0, dimmer=0))[0] is False changed, output_dto = cache.handle_change( OutputStateDTO(1, status=True, dimmer=100)) assert output_dto.state.dimmer == 100 assert changed is True changed, output_dto = cache.handle_change(OutputStateDTO(1, dimmer=50)) assert output_dto.state.dimmer is 50 assert changed is True # Change lock. assert cache.handle_change(OutputStateDTO(0, locked=False))[0] is False changed, output_dto = cache.handle_change( OutputStateDTO(1, locked=True)) assert output_dto.state.locked is True assert changed is True
def test_load_outputs(self): select_mock = mock.Mock() select_mock.join_from.return_value = [ Output(id=1, number=42, room=Room(id=2, number=3)) ] with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', return_value=OutputDTO(id=42)) as load: outputs = self.controller.load_outputs() assert OutputDTO(id=42, room=3) in outputs load.assert_called_with(output_id=42)
def test_load_output(self): where_mock = mock.Mock() where_mock.get.return_value = Output(id=1, number=42, room=Room(id=2, number=3)) join_from_mock = mock.Mock() join_from_mock.where.return_value = where_mock select_mock = mock.Mock() select_mock.join_from.return_value = join_from_mock with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', return_value=OutputDTO(id=42)) as load: output = self.controller.load_output(42) assert output == OutputDTO(id=42, room=3) load.assert_called_with(output_id=42)
def deserialize(api_data): # type: (Dict) -> Tuple[OutputDTO, List[str]] loaded_fields = ['id'] output_dto = OutputDTO(api_data['id']) loaded_fields += SerializerToolbox.deserialize( dto=output_dto, # Referenced api_data=api_data, mapping={ 'module_type': ('module_type', None), 'name': ('name', None), 'type': ('output_type', None), 'lock_bit_id': ('lock_bit_id', OutputSerializer.BYTE_MAX), 'timer': ('timer', OutputSerializer.WORD_MAX), 'floor': ('floor', OutputSerializer.BYTE_MAX), 'room': ('room', OutputSerializer.BYTE_MAX) }) for i in range(4): base_field = 'can_led_{0}'.format(i + 1) id_field = '{0}_id'.format(base_field) function_field = '{0}_function'.format(base_field) if id_field in api_data and function_field in api_data: loaded_fields.append(base_field) setattr( output_dto, base_field, FeedbackLedDTO(id=api_data[id_field], function=api_data[function_field])) return output_dto, loaded_fields
def test_validation_bits_passthrough(self): # Important note: bits are ordened per byte, so the sequence is like: # [[7, 6, 5, 4, 3, 2, 1, 0], [15, 14, 13, 12, 11, 10, 9, 8], [23, 22, ...], ...] bit_data = [ 0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000 ] def _do_command(cmd, fields): start = fields['number'] // 8 return {'data': bit_data[start:start + 11]} classic = get_classic_controller_dummy() classic._master_communicator.do_command = _do_command classic._master_version = (0, 0, 0) pubsub = get_pubsub() bits = classic.load_validation_bits() self.assertIsNone(bits) classic._master_version = (3, 143, 102) bits = classic.load_validation_bits() expected_bits = {i: False for i in range(256)} expected_bits[1] = True expected_bits[254] = True self.assertEqual(expected_bits, bits) events = [] def _on_event(master_event): if master_event.type == MasterEvent.Types.OUTPUT_STATUS: events.append(master_event.data) pubsub.subscribe_master_events(PubSub.MasterTopics.OUTPUT, _on_event) classic._validation_bits = ValidationBitStatus( on_validation_bit_change=classic._validation_bit_changed) classic._output_config = {0: OutputDTO(0, lock_bit_id=5)} pubsub._publish_all_events() classic._refresh_validation_bits() classic._on_master_validation_bit_change(5, True) classic._on_master_validation_bit_change(6, True) classic._on_master_validation_bit_change(5, False) pubsub._publish_all_events() self.assertEqual([{ 'id': 0, 'locked': False }, { 'id': 0, 'locked': True }, { 'id': 0, 'locked': False }], events)
def test_master_output_event(self): events = [] def _on_event(master_event): events.append(master_event) classic = get_classic_controller_dummy() pubsub = get_pubsub() pubsub.subscribe_master_events(PubSub.MasterTopics.OUTPUT, _on_event) classic._output_config = {0: OutputDTO(id=0), 1: OutputDTO(id=1), 2: OutputDTO(id=2, room=3)} pubsub._publish_all_events() events = [] classic._on_master_output_event({'outputs': [(0, 0), (2, 5)]}) pubsub._publish_all_events() self.assertEqual(events, [MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=0, status=True, dimmer=0)}), MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=1, status=False)}), MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=2, status=True, dimmer=5)})])
def test_get_output_status(self): select_mock = mock.Mock() select_mock.join_from.return_value = [ Output(id=0, number=2), Output(id=1, number=40, room=Room(id=2, number=3)) ] with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', side_effect=lambda output_id: OutputDTO(id=output_id)), \ mock.patch.object(self.master_controller, 'load_output_status', return_value=[OutputStateDTO(id=2, status=False), OutputStateDTO(id=40, status=True)]): self.controller._sync_state() status = self.controller.get_output_status(40) assert status == OutputStateDTO(id=40, status=True)
def test_get_output_statuses(self): select_mock = mock.Mock() select_mock.join_from.return_value = [ Output(id=0, number=2), Output(id=1, number=40, module_type='D', room=Room(id=2, number=3)) ] with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', side_effect=lambda output_id: OutputDTO(id=output_id)), \ mock.patch.object(self.master_controller, 'load_output_status', return_value=[OutputStateDTO(id=2, status=False, dimmer=0), OutputStateDTO(id=40, status=True, dimmer=50)]): self.controller._sync_state() status = self.controller.get_output_statuses() assert len(status) == 2 assert OutputStateDTO(id=2, status=False) in status assert OutputStateDTO(id=40, status=True, dimmer=50) in status
def test_orm_sync(self): events = [] def handle_event(gateway_event): events.append(gateway_event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.CONFIG, handle_event) output_dto = OutputDTO(id=42) with mock.patch.object(self.master_controller, 'load_outputs', return_value=[output_dto]): self.controller.run_sync_orm() self.pubsub._publish_all_events() assert Output.select().where( Output.number == output_dto.id).count() == 1 assert GatewayEvent(GatewayEvent.Types.CONFIG_CHANGE, {'type': 'output'}) in events assert len(events) == 1
def test_can_feedback_controller_calls(self): with mock.patch.object(CANFeedbackController, 'load_global_led_feedback_configuration') as call: self.controller.load_global_feedback(0) call.assert_called_once() with mock.patch.object(CANFeedbackController, 'load_global_led_feedback_configuration') as call: self.controller.load_global_feedbacks() call.assert_called_once() with mock.patch.object(CANFeedbackController, 'save_global_led_feedback_configuration') as call: self.controller.save_global_feedbacks([]) call.assert_called_once() with mock.patch.object(CANFeedbackController, 'load_output_led_feedback_configuration') as call: self.controller.load_output(0) call.assert_called_once() with mock.patch.object(CANFeedbackController, 'save_output_led_feedback_configuration') as call: self.controller.save_outputs([OutputDTO(id=0)]) call.assert_called_once()
def test_individual_feedback_leds(self): output = OutputConfiguration.deserialize({'id': 0}) # Setup basic LED feedback output_dto = OutputDTO( id=0, can_led_1=FeedbackLedDTO( id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL), can_led_3=FeedbackLedDTO( id=7, function=FeedbackLedDTO.Functions.MB_B8_INVERTED)) # Save led feedback config CANFeedbackController.save_output_led_feedback_configuration( output, output_dto) # Validate correct data in created GA self.assertEqual(0, output.output_groupaction_follow) group_action = GroupActionController.load_group_action(0) self.assertEqual([ BasicAction( action_type=20, action=50, device_nr=5, extra_parameter=65280), BasicAction( action_type=20, action=51, device_nr=7, extra_parameter=32514) ], group_action.actions) self.assertEqual('Output 0', group_action.name) # Alter GA extra_ba = BasicAction(action_type=123, action=123) # Some random BA group_action.actions.append(extra_ba) group_action.name = 'Foobar' GroupActionController.save_group_action(group_action, ['name', 'actions']) # Validate loading data output_dto = OutputDTO(id=0) CANFeedbackController.load_output_led_feedback_configuration( output, output_dto) self.assertEqual( FeedbackLedDTO(id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL), output_dto.can_led_1) self.assertEqual( FeedbackLedDTO(id=7, function=FeedbackLedDTO.Functions.MB_B8_INVERTED), output_dto.can_led_2) # Moved to 2 # Change led feedback config output_dto.can_led_2.function = FeedbackLedDTO.Functions.ON_B8_INVERTED CANFeedbackController.save_output_led_feedback_configuration( output, output_dto) # Validate stored led feedback data output_dto = OutputDTO(id=0) CANFeedbackController.load_output_led_feedback_configuration( output, output_dto) self.assertEqual( FeedbackLedDTO(id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL), output_dto.can_led_1) self.assertEqual( FeedbackLedDTO(id=7, function=FeedbackLedDTO.Functions.ON_B8_INVERTED), output_dto.can_led_2) # Validate GA changes group_action = GroupActionController.load_group_action(0) self.assertEqual([extra_ba] + [ BasicAction( action_type=20, action=50, device_nr=5, extra_parameter=65280), BasicAction( action_type=20, action=51, device_nr=7, extra_parameter=32512) ], group_action.actions) self.assertEqual('Foobar', group_action.name)
def test_output_sync_change(self): events = [] def on_change(gateway_event): events.append(gateway_event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, on_change) outputs = {2: OutputDTO(id=2), 40: OutputDTO(id=40, module_type='D')} select_mock = mock.Mock() select_mock.join_from.return_value = [ Output(id=0, number=2), Output(id=1, number=40, room=Room(id=2, number=3)) ] with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', side_effect=lambda output_id: outputs.get(output_id)), \ mock.patch.object(self.master_controller, 'load_output_status', return_value=[OutputStateDTO(id=2, status=True), OutputStateDTO(id=40, status=True)]): self.controller._sync_state() self.pubsub._publish_all_events() assert [ GatewayEvent( 'OUTPUT_CHANGE', { 'id': 2, 'status': { 'on': True, 'locked': False }, 'location': { 'room_id': 255 } }), GatewayEvent( 'OUTPUT_CHANGE', { 'id': 40, 'status': { 'on': True, 'value': 0, 'locked': False }, 'location': { 'room_id': 3 } }) ] == events select_mock = mock.Mock() select_mock.join_from.return_value = [ Output(id=0, number=2), Output(id=1, number=40, room=Room(id=2, number=3)) ] with mock.patch.object(Output, 'select', return_value=select_mock), \ mock.patch.object(self.master_controller, 'load_output', side_effect=lambda output_id: outputs.get(output_id)), \ mock.patch.object(self.master_controller, 'load_output_status', return_value=[OutputStateDTO(id=2, status=True, dimmer=0), OutputStateDTO(id=40, status=True, dimmer=50)]): events = [] self.controller._sync_state() self.pubsub._publish_all_events() assert [ GatewayEvent( 'OUTPUT_CHANGE', { 'id': 2, 'status': { 'on': True, 'locked': False }, 'location': { 'room_id': 255 } }), GatewayEvent( 'OUTPUT_CHANGE', { 'id': 40, 'status': { 'on': True, 'value': 50, 'locked': False }, 'location': { 'room_id': 3 } }) ] == events
def test_output_master_change(self): events = [] def on_change(gateway_event): events.append(gateway_event) self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE, on_change) self.controller._cache.update_outputs( [OutputDTO(id=2), OutputDTO(id=40, module_type='D', room=3)]) self.controller._handle_master_event( MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=2, status=False)})) self.controller._handle_master_event( MasterEvent( 'OUTPUT_STATUS', {'state': OutputStateDTO(id=40, status=True, dimmer=100)})) self.pubsub._publish_all_events() events = [] self.controller._handle_master_event( MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=2, status=True)})) self.controller._handle_master_event( MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=40, status=True)})) self.pubsub._publish_all_events() assert [ GatewayEvent( 'OUTPUT_CHANGE', { 'id': 2, 'status': { 'on': True, 'locked': False }, 'location': { 'room_id': 255 } }) ] == events events = [] self.controller._handle_master_event( MasterEvent('OUTPUT_STATUS', {'state': OutputStateDTO(id=40, dimmer=50)})) self.pubsub._publish_all_events() assert [ GatewayEvent( 'OUTPUT_CHANGE', { 'id': 40, 'status': { 'on': True, 'value': 50, 'locked': False }, 'location': { 'room_id': 3 } }) ] == events
def test_output_mapper_timer(self): # Inactive orm = OutputMapper.dto_to_orm(OutputDTO(id=0, timer=0), fields=['timer']) self.assertEqual(OutputConfiguration.TimerType.INACTIVE, orm.timer_type) self.assertEqual(0, orm.timer_value) dto = OutputMapper.orm_to_dto( OutputConfiguration.deserialize({ 'id': 0, 'timer_type': OutputConfiguration.TimerType.INACTIVE, 'timer_value': 123, 'name': 'test', 'output_type': 0, 'module': { 'id': 0, 'device_type': 'O' } })) self.assertEqual( OutputDTO(id=0, timer=None, name='test', output_type=0, module_type='O'), dto) dto = OutputMapper.orm_to_dto( OutputConfiguration.deserialize({ 'id': 0, 'timer_type': OutputConfiguration.TimerType.ABSOLUTE, 'timer_value': 123, 'name': 'test', 'output_type': 0, 'module': { 'id': 0, 'device_type': 'O' } })) self.assertEqual( OutputDTO(id=0, timer=None, name='test', output_type=0, module_type='O'), dto) # In seconds orm = OutputMapper.dto_to_orm(OutputDTO(id=0, timer=123), fields=['timer']) self.assertEqual(OutputConfiguration.TimerType.PER_1_S, orm.timer_type) self.assertEqual(123, orm.timer_value) dto = OutputMapper.orm_to_dto( OutputConfiguration.deserialize({ 'id': 0, 'timer_type': OutputConfiguration.TimerType.PER_1_S, 'timer_value': 123, 'name': 'test', 'output_type': 0, 'module': { 'id': 0, 'device_type': 'O' } })) self.assertEqual( OutputDTO(id=0, timer=123, name='test', output_type=0, module_type='O'), dto) # In milliseconds dto = OutputMapper.orm_to_dto( OutputConfiguration.deserialize({ 'id': 0, 'timer_type': OutputConfiguration.TimerType.PER_100_MS, 'timer_value': 123, 'name': 'test', 'output_type': 0, 'module': { 'id': 0, 'device_type': 'O' } })) self.assertEqual( OutputDTO(id=0, timer=12, name='test', output_type=0, module_type='O'), dto)