Beispiel #1
0
    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(events, [{'state': OutputStateDTO(id=0, locked=False)},
                                  {'state': OutputStateDTO(id=0, locked=True)},
                                  {'state': OutputStateDTO(id=0, locked=False)}])
Beispiel #2
0
 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)
Beispiel #3
0
 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
Beispiel #4
0
    def test_master_output_event(self):
        events = []

        def _on_event(master_event):
            events.append(master_event)

        self.pubsub.subscribe_master_events(PubSub.MasterTopics.OUTPUT, _on_event)

        events = []
        self.controller._handle_event({'type': 0, 'device_nr': 0, 'action': 0, 'data': bytearray([255, 0, 0, 0])})
        self.controller._handle_event({'type': 0, 'device_nr': 2, 'action': 1, 'data': bytearray([100, 2, 0xff, 0xfe])})
        self.controller._handle_event({'type': 0, 'device_nr': 4, 'action': 2, 'data': bytearray([1, 0, 0, 0])})
        self.controller._handle_event({'type': 0, 'device_nr': 6, 'action': 2, 'data': bytearray([0, 0, 0, 0])})
        self.pubsub._publish_all_events()
        self.assertEqual([MasterEvent(MasterEvent.Types.OUTPUT_STATUS, {'state': OutputStateDTO(id=0, status=False, dimmer=255, ctimer=0)}),
                          MasterEvent(MasterEvent.Types.OUTPUT_STATUS, {'state': OutputStateDTO(id=2, status=True, dimmer=100, ctimer=65534)}),
                          MasterEvent(MasterEvent.Types.OUTPUT_STATUS, {'state': OutputStateDTO(id=4, locked=True)}),
                          MasterEvent(MasterEvent.Types.OUTPUT_STATUS, {'state': OutputStateDTO(id=6, locked=False)})],
                         events)
    def test_master_shutter_event(self):
        events = []

        def _on_event(master_event):
            events.append(master_event)

        self.pubsub.subscribe_master_events(PubSub.MasterTopics.SHUTTER, _on_event)

        self.controller._output_states = {0: OutputStateDTO(id=0, status=False),
                                          10: OutputStateDTO(id=10, status=False),
                                          11: OutputStateDTO(id=11, status=False)}
        self.controller._output_shutter_map = {10: 1, 11: 1}
        self.controller._shutter_status = {1: (False, False)}
        self.pubsub._publish_all_events()

        with mock.patch.object(gateway.hal.master_controller_core, 'ShutterConfiguration',
                               side_effect=get_core_shutter_dummy):
            events = []
            self.controller._handle_event({'type': 0, 'device_nr': 10, 'action': 0, 'data': [None, 0, 0, 0]})
            self.controller._handle_event({'type': 0, 'device_nr': 11, 'action': 0, 'data': [None, 0, 0, 0]})
            self.pubsub._publish_all_events()
            assert [] == events

            events = []
            self.controller._handle_event({'type': 0, 'device_nr': 10, 'action': 1, 'data': [None, 0, 0, 0]})
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'going_up', 'location': {'room_id': 255}})] == events

            events = []
            self.controller._handle_event({'type': 0, 'device_nr': 11, 'action': 1, 'data': [None, 0, 0, 0]})
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'stopped', 'location': {'room_id': 255}})] == events

            events = []
            self.controller._handle_event({'type': 0, 'device_nr': 10, 'action': 0, 'data': [None, 0, 0, 0]})
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'going_down', 'location': {'room_id': 255}})] == events

            events = []
            self.controller._handle_event({'type': 0, 'device_nr': 11, 'action': 0, 'data': [None, 0, 0, 0]})
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'stopped', 'location': {'room_id': 255}})] == events
Beispiel #6
0
    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 update_outputs(self, output_dtos):
     # type: (List[OutputDTO]) -> None
     with self._lock:
         new_state = {}
         for output_dto in output_dtos:
             output_dto = copy.copy(output_dto)
             if output_dto.id in self._cache:
                 output_dto.state = self._cache[output_dto.id].state
             else:
                 output_dto.state = OutputStateDTO(output_dto.id)
             new_state[output_dto.id] = output_dto
         self._cache = new_state
         self._loaded = True
Beispiel #8
0
 def deserialize(api_data):
     # type: (Dict) -> OutputStateDTO
     output_state_dto = OutputStateDTO(api_data['id'])
     SerializerToolbox.deserialize(
         dto=output_state_dto,  # Referenced
         api_data=api_data,
         mapping={
             'status': ('status', bool),
             'ctimer': ('ctimer', lambda x: x or 0),
             'dimmer': ('dimmer', lambda x: x or 0),
             'locked': ('locked', lambda x: x or False)
         })
     return output_state_dto
Beispiel #9
0
 def test_output_status(self):
     with mock.patch.object(
             self.output_controller,
             'get_output_statuses',
             return_value=[OutputStateDTO(id=0, status=True)]):
         response = self.web.get_output_status()
         self.assertEqual([{
             'id': 0,
             'status': 1,
             'ctimer': 0,
             'dimmer': 0,
             'locked': False
         }],
                          json.loads(response)['status'])
Beispiel #10
0
 def deserialize(api_data):
     # type: (Dict) -> Tuple[OutputStateDTO, List[str]]
     loaded_fields = ['id']
     output_state_dto = OutputStateDTO(api_data['id'])
     loaded_fields += SerializerToolbox.deserialize(
         dto=output_state_dto,  # Referenced
         api_data=api_data,
         mapping={
             'status': ('status', bool),
             'ctimer': ('ctimer', lambda x: x or 0),
             'dimmer': ('dimmer', lambda x: x or 0),
             'locked': ('locked', lambda x: x or False)
         })
     return output_state_dto, loaded_fields
 def setUp(self):
     self.test_db = SqliteDatabase(':memory:')
     self.test_db.bind(MODELS)
     self.test_db.connect()
     self.test_db.create_tables(MODELS)
     self._gateway_api = mock.Mock(GatewayApi)
     self._gateway_api.get_timezone.return_value = 'Europe/Brussels'
     self._gateway_api.get_sensor_temperature_status.return_value = 10.0
     output_controller = mock.Mock(OutputController)
     output_controller.get_output_status.return_value = OutputStateDTO(id=0, status=False)
     SetUpTestInjections(gateway_api=self._gateway_api,
                         output_controller=output_controller,
                         pubsub=mock.Mock())
     self._thermostat_controller = ThermostatControllerGateway()
     SetUpTestInjections(thermostat_controller=self._thermostat_controller)
     self._thermostat_group = ThermostatGroup.create(number=0,
                                                     name='thermostat group',
                                                     on=True,
                                                     threshold_temperature=10.0,
                                                     sensor=Sensor.create(number=1),
                                                     mode='heating')
Beispiel #12
0
    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
Beispiel #13
0
    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
Beispiel #14
0
    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
Beispiel #15
0
    def test_master_shutter_refresh(self):
        events = []

        def _on_event(master_event):
            events.append(master_event)

        self.pubsub.subscribe_master_events(PubSub.MasterTopics.SHUTTER, _on_event)

        output_status = [OutputStateDTO(id=0, status=False, dimmer=0),
                         OutputStateDTO(id=1, status=False, dimmer=0),
                         OutputStateDTO(id=10, status=False, dimmer=0),
                         OutputStateDTO(id=11, status=False, dimmer=0)]
        with mock.patch.object(gateway.hal.master_controller_core, 'ShutterConfiguration',
                               side_effect=get_core_shutter_dummy), \
             mock.patch.object(self.controller, 'load_output_status', return_value=output_status):
            events = []
            self.controller._refresh_shutter_states()
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'stopped', 'location': {'room_id': 255}})] == events

        output_status = [OutputStateDTO(id=0, status=False, dimmer=0),
                         OutputStateDTO(id=1, status=True, dimmer=0),
                         OutputStateDTO(id=10, status=True, dimmer=0),
                         OutputStateDTO(id=11, status=False, dimmer=0)]
        with mock.patch.object(gateway.hal.master_controller_core, 'ShutterConfiguration',
                               side_effect=get_core_shutter_dummy), \
             mock.patch.object(self.controller, 'load_output_status', return_value=output_status):
            events = []
            self.controller._refresh_shutter_states()
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'going_up', 'location': {'room_id': 255}})] == events

        output_status = [OutputStateDTO(id=0, status=False, dimmer=0),
                         OutputStateDTO(id=1, status=True, dimmer=0),
                         OutputStateDTO(id=10, status=False, dimmer=0),
                         OutputStateDTO(id=11, status=True, dimmer=0)]
        with mock.patch.object(gateway.hal.master_controller_core, 'ShutterConfiguration',
                               side_effect=get_core_shutter_dummy), \
             mock.patch.object(self.controller, 'load_output_status', return_value=output_status):
            events = []
            self.controller._refresh_shutter_states()
            self.pubsub._publish_all_events()
            assert [MasterEvent('SHUTTER_CHANGE', {'id': 1, 'status': 'going_down', 'location': {'room_id': 255}})] == events
Beispiel #16
0
    def test_get_special_methods(self):
        """ Test getting special methods on a plugin. """
        controller = None
        try:
            PluginControllerTest._create_plugin(
                'P1', """
import time
from plugins.base import *

class P1(OMPluginBase):
    name = 'P1'
    version = '0.1.0'
    interfaces = [('webui', '1.0')]

    def __init__(self, webservice, logger):
        OMPluginBase.__init__(self, webservice, logger)
        self._bg_running = False
        self._input_data = None
        self._input_data_version_2 = None
        self._output_data = None
        self._output_data_version_2 = None
        self._event_data = None

    @om_expose(auth=True)
    def html_index(self):
        return 'HTML'

    @om_expose(auth=False)
    def get_log(self):
        return {'bg_running': self._bg_running,
                'input_data': self._input_data,
                'input_data_version_2': self._input_data_version_2,
                'output_data': self._output_data,
                'output_data_version_2': self._output_data_version_2,
                'event_data': self._event_data}

    @input_status
    def input(self, input_status_inst):
        self._input_data = input_status_inst
        
    @input_status(version=2)
    def input_version_2(self, input_status_inst):
        self._input_data_version_2 = input_status_inst
        
    @output_status
    def output(self, output_status_inst):
        self._output_data = output_status_inst
        
    @output_status(version=2)
    def output_version_2(self, output_status_inst):
        self._output_data_version_2 = output_status_inst
        
    @receive_events
    def recv_events(self, code):
        self._event_data = code

    @background_task
    def run(self):
        while True:
            self._bg_running = True
            time.sleep(1)
""")

            output_controller = Mock(OutputController)
            output_controller.get_output_statuses = lambda: [
                OutputStateDTO(id=1, status=True, dimmer=5)
            ]
            controller = PluginControllerTest._get_controller(
                output_controller=output_controller)
            controller.start()

            response = controller._request('P1', 'html_index')
            self.assertEqual(response, 'HTML')

            rising_input_event = {
                'id': 1,
                'status': True,
                'location': {
                    'room_id': 1
                }
            }
            controller.process_observer_event(
                GatewayEvent(event_type=GatewayEvent.Types.INPUT_CHANGE,
                             data=rising_input_event))
            falling_input_event = {
                'id': 2,
                'status': False,
                'location': {
                    'room_id': 5
                }
            }
            controller.process_observer_event(
                GatewayEvent(event_type=GatewayEvent.Types.INPUT_CHANGE,
                             data=falling_input_event))
            output_event = {
                'id': 1,
                'status': {
                    'on': True,
                    'value': 5,
                    'locked': True
                },
                'location': {
                    'room_id': 5
                }
            }
            controller.process_observer_event(
                GatewayEvent(event_type=GatewayEvent.Types.OUTPUT_CHANGE,
                             data=output_event))
            controller.process_event(1)

            keys = [
                'input_data', 'input_data_version_2', 'output_data',
                'output_data_version_2', 'event_data'
            ]
            start = time.time()
            while time.time() - start < 2:
                response = controller._request('P1', 'get_log')
                if all(response[key] is not None for key in keys):
                    break
                time.sleep(0.1)
            self.assertEqual(response['bg_running'], True)
            self.assertEqual(
                response['input_data'],
                [1, None])  # only rising edges should be triggered
            self.assertEqual(response['output_data'], [[1, 5]])
            self.assertEqual(response['output_data_version_2'], output_event)
            self.assertEqual(response['event_data'], 1)
        finally:
            if controller is not None:
                controller.stop()
            PluginControllerTest._destroy_plugin('P1')