Beispiel #1
0
 def test_load_ventilation(self):
     with mock.patch.object(Ventilation,
                            'get',
                            return_value=Ventilation(
                                id=42,
                                source='plugin',
                                external_id='device-000001',
                                name='foo',
                                amount_of_levels=4,
                                device_vendor='example',
                                device_type='model-0',
                                device_serial='device-000001',
                                plugin=Plugin(id=2,
                                              name='dummy',
                                              version='0.0.1'))):
         ventilation_dto = self.controller.load_ventilation(42)
         assert ventilation_dto == VentilationDTO(
             id=42,
             external_id='device-000001',
             source=VentilationSourceDTO(id=2, name='dummy', type='plugin'),
             name='foo',
             amount_of_levels=4,
             device_vendor='example',
             device_type='model-0',
             device_serial='device-000001')
Beispiel #2
0
 def test_update_existing_ventilation(self):
     plugin = Plugin(id=2, name='dummy', version='0.0.1')
     with mock.patch.object(Plugin, 'get', return_value=plugin), \
          mock.patch.object(Ventilation, 'get_or_none',
                            return_value=Ventilation(id=42,
                                                     source='plugin',
                                                     source_id=2,
                                                     external_id='device-000001',
                                                     name='foo',
                                                     amount_of_levels=4,
                                                     device_type='model-0',
                                                     device_vendor='example',
                                                     device_serial='device-000001',
                                                     plugin=plugin)) as get_or_none, \
          mock.patch.object(Ventilation, 'save', return_value=1) as save:
         ventilation_dto = VentilationDTO(id=42,
                                          external_id='device-000001',
                                          source=VentilationSourceDTO(
                                              id=2,
                                              name='dummy',
                                              type='plugin'),
                                          name='foo',
                                          amount_of_levels=4,
                                          device_vendor='example',
                                          device_type='model-0',
                                          device_serial='device-000001')
         self.controller.save_ventilation(ventilation_dto)
         get_or_none.assert_called_with(id=42,
                                        source='plugin',
                                        plugin=plugin,
                                        external_id='device-000001')
         save.assert_called()
Beispiel #3
0
 def dto_to_orm(ventilation_dto, fields):
     # type: (VentilationDTO, List[str]) -> Ventilation
     lookup_kwargs = {}  # type: Dict[str,Any]
     if ventilation_dto.id:
         lookup_kwargs.update({'id': ventilation_dto.id})
     if ventilation_dto.source.is_plugin:
         plugin = Plugin.get(name=ventilation_dto.source.name)
         lookup_kwargs.update({
             'plugin': plugin,
             'source': ventilation_dto.source.type,
             'external_id': ventilation_dto.external_id
         })
     ventilation = Ventilation.get_or_none(**lookup_kwargs)
     if ventilation is None:
         ventilation = Ventilation(**lookup_kwargs)
     if 'name' in fields:
         ventilation.name = ventilation_dto.name
     if 'amount_of_levels' in fields:
         ventilation.amount_of_levels = ventilation_dto.amount_of_levels
     if 'device' in fields:
         ventilation.device_vendor = ventilation_dto.device_vendor
         ventilation.device_type = ventilation_dto.device_type
         if ventilation_dto.device_serial:
             ventilation.device_serial = ventilation_dto.device_serial
     return ventilation
Beispiel #4
0
 def test_set_invalid_level(self):
     plugin = Plugin(id=2, name='dummy', version='0.0.1')
     with mock.patch.object(Select, 'count', return_value=1), \
          mock.patch.object(Ventilation, 'get',
                            return_value=Ventilation(id=42, amount_of_levels=4, souurce='plugin', plugin=plugin)):
         self.assertRaises(ValueError, self.controller.set_level, 42, 5)
         self.assertRaises(ValueError, self.controller.set_level, 42, -1)
Beispiel #5
0
 def _update_orm(name, version):
     # type: (str, str) -> None
     try:
         plugin, _ = Plugin.get_or_create(name=name, defaults={'version': version})
         if plugin.version != version:
             plugin.version = version
             plugin.save()
     except Exception as ex:
         logger.error('Could not store Plugin version: {0}'.format(ex))
Beispiel #6
0
    def test_ventilation_controller_inactive_status(self):
        plugin = Plugin(id=2, name='dummy', version='0.0.1')

        def get_ventilation(id):
            return Ventilation(id=id,
                               amount_of_levels=4,
                               source='plugin',
                               plugin=plugin)

        with mock.patch.object(Select, 'count', return_value=1), \
                mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \
                mock.patch.object(Ventilation, 'select',
                                  return_value=[get_ventilation(43)]):
            events = []

            def callback(event):
                events.append(event)

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE,
                                                 callback)

            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=2,
                                     timer=60.0,
                                     last_seen=(time.time() - 600)))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))

            self.controller._check_connected_timeout()
            self.pubsub._publish_all_events()
            self.assertEqual(2, len(events))
            self.assertEqual(1, len(self.controller._status))

            # Check that the last event that has been send is Null
            last_event = events[-1]
            self.assertEqual(None, last_event.data['mode'])
            self.assertEqual(None, last_event.data['level'])

            self.controller.set_status(
                VentilationStatusDTO(43, 'manual', level=2, timer=60.0))
            self.pubsub._publish_all_events()

            self.assertEqual(3, len(events))
            self.assertEqual(1, len(self.controller._status))

            self.controller._check_connected_timeout()
            self.pubsub._publish_all_events()
            # Now there would no timeout occur
            self.assertEqual(3, len(events))
            self.assertEqual(1, len(self.controller._status))
Beispiel #7
0
    def remove_plugin(self, name):
        """
        Remove a plugin, this removes the plugin package and configuration.
        It also calls the remove function on the plugin to cleanup other files written by the
        plugin.
        """
        from shutil import rmtree

        plugin = self._get_plugin(name)

        # Check if the plugin in installed
        if plugin is None:
            Plugin.delete().where(Plugin.name == name).execute()
            raise Exception('Plugin \'{0}\' is not installed.'.format(name))

        # Execute the on_remove callbacks
        try:
            plugin.remove_callback()
        except Exception as exception:
            logger.error('Exception while removing plugin \'{0}\': {1}'.format(name, exception))

        # Stop the plugin process
        self._destroy_plugin_runner(name)
        self._update_dependencies()

        # Remove the plugin package
        plugin_path = '{0}/{1}'.format(self._plugins_path, name)
        try:
            rmtree(plugin_path)
        except Exception as exception:
            raise Exception('Error while removing package for plugin \'{0}\': {1}'.format(name, exception))

        # Remove the plugin configuration
        conf_file = '{0}/pi_{1}.conf'.format(self._plugin_config_path, name)
        if os.path.exists(conf_file):
            os.remove(conf_file)

        # Finally remove database entry.
        Plugin.delete().where(Plugin.name == name).execute()

        return {'msg': 'Plugin successfully removed'}
Beispiel #8
0
 def get_plugins(self):
     # type: () -> List[PluginRunner]
     """
     Get a list of all installed plugins.
     """
     plugins = []
     for plugin_orm in list(Plugin.select()):
         plugin = self._runners.get(plugin_orm.name)
         if plugin:
             plugins.append(plugin)
         else:
             logger.warning('missing runner for plugin {}'.format(plugin_orm.name))
     return plugins
Beispiel #9
0
    def test_update_plugin(self):
        """ Validates whether a plugin can be updated """
        test_1_md5, test_1_data = PluginControllerTest._create_plugin_package(
            'Test', """
from plugins.base import *

class Test(OMPluginBase):
    name = 'Test'
    version = '0.0.1'
    interfaces = []
""")
        test_2_md5, test_2_data = PluginControllerTest._create_plugin_package(
            'Test', """
from plugins.base import *

class Test(OMPluginBase):
    name = 'Test'
    version = '0.0.2'
    interfaces = []
""")

        controller = PluginControllerTest._get_controller()
        controller.start()

        # Install first version
        result = controller.install_plugin(test_1_md5, test_1_data)
        self.assertEqual(result, 'Plugin successfully installed')
        controller.start_plugin('Test')
        self.assertEqual([r.name for r in controller.get_plugins()], ['Test'])
        plugin = Plugin.get(name='Test')
        self.assertEqual('0.0.1', plugin.version)

        # Update to version 2
        result = controller.install_plugin(test_2_md5, test_2_data)
        self.assertEqual(result, 'Plugin successfully installed')
        self.assertEqual([r.name for r in controller.get_plugins()], ['Test'])
        plugin = Plugin.get(name='Test')
        self.assertEqual('0.0.2', plugin.version)
Beispiel #10
0
 def test_set_level(self):
     plugin = Plugin(id=2, name='dummy', version='0.0.1')
     with mock.patch.object(Select, 'count', return_value=1), \
          mock.patch.object(Ventilation, 'get',
                            side_effect=[Ventilation(id=42, amount_of_levels=4, source='plugin', plugin=plugin),
                                         Ventilation(id=43, amount_of_levels=4, source='plugin', plugin=plugin)]), \
          mock.patch.object(Ventilation, 'select',
                            return_value=[Ventilation(id=42, amount_of_levels=4, source='plugin', plugin=plugin),
                                          Ventilation(id=43, amount_of_levels=4, source='plugin', plugin=plugin)]):
         self.controller.set_level(42, 0)
         self.controller.set_level(43, 2, timer=60.0)
         status = self.controller.get_status()
         assert {'manual'} == set(x.mode for x in status)
         assert {42, 43} == set(x.id for x in status)
         assert {0, 2} == set(x.level for x in status)
         assert {None, 60.0} == set(x.timer for x in status)
Beispiel #11
0
    def test_ventilation_config_events(self):
        plugin = Plugin(id=2, name='dummy', version='0.0.1')
        with mock.patch.object(Plugin, 'get', return_value=plugin), \
                mock.patch.object(Ventilation, 'get_or_none',
                                  return_value=Ventilation(id=42,
                                                           source='plugin',
                                                           source_id=2,
                                                           external_id='device-000001',
                                                           name='foo',
                                                           amount_of_levels=4,
                                                           device_type='model-0',
                                                           device_vendor='example',
                                                           device_serial='device-000001',
                                                           plugin=plugin)), \
                mock.patch.object(Ventilation, 'save', side_effect=(0, 1)):

            events = []

            def callback(event):
                events.append(event)

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.CONFIG,
                                                 callback)

            ventilation_dto = VentilationDTO(id=42,
                                             external_id='device-000001',
                                             source=VentilationSourceDTO(
                                                 id=2,
                                                 name='dummy',
                                                 type='plugin'),
                                             name='foo',
                                             amount_of_levels=4,
                                             device_vendor='example',
                                             device_type='model-0',
                                             device_serial='device-000001')
            self.controller.save_ventilation(ventilation_dto)
            self.pubsub._publish_all_events()
            assert len(events) == 0, events  # No change

            ventilation_dto.name = 'bar'
            self.controller.save_ventilation(ventilation_dto)
            self.pubsub._publish_all_events()
            assert GatewayEvent(GatewayEvent.Types.CONFIG_CHANGE,
                                {'type': 'ventilation'}) in events
            assert len(events) == 1, events
Beispiel #12
0
    def test_ventilation_change_events(self):
        plugin = Plugin(id=2, name='dummy', version='0.0.1')

        def get_ventilation(id):
            return Ventilation(id=id,
                               amount_of_levels=4,
                               source='plugin',
                               plugin=plugin)

        with mock.patch.object(Select, 'count', return_value=1), \
             mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \
             mock.patch.object(Ventilation, 'select',
                               return_value=[get_ventilation(42), get_ventilation(43)]):
            self.controller.set_status(
                VentilationStatusDTO(42, 'manual', level=0))
            self.controller.set_status(
                VentilationStatusDTO(43, 'manual', level=2, timer=60.0))
            self.pubsub._publish_all_events()

            events = []

            def callback(event):
                events.append(event)

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE,
                                                 callback)

            self.controller.set_status(
                VentilationStatusDTO(42, 'manual', level=0))
            self.controller.set_status(
                VentilationStatusDTO(43, 'manual', level=2, timer=60.0))
            self.pubsub._publish_all_events()
            assert GatewayEvent(
                GatewayEvent.Types.VENTILATION_CHANGE, {
                    'id': 43,
                    'mode': 'manual',
                    'level': 2,
                    'timer': 60.0,
                    'remaining_time': None,
                    'is_connected': True
                }) in events
            assert len(events) == 1, events
Beispiel #13
0
    def test_get_one_plugin(self):
        """ Test getting one plugin in the plugins package. """
        controller = None
        try:
            PluginControllerTest._create_plugin(
                'P1', """
from plugins.base import *

class P1(OMPluginBase):
    name = 'P1'
    version = '1.0.0'
    interfaces = []
""")
            controller = PluginControllerTest._get_controller()
            controller.start()
            plugin_list = controller.get_plugins()
            self.assertEqual(1, len(plugin_list))
            self.assertEqual('P1', plugin_list[0].name)
            plugin = Plugin.get(name='P1')
            self.assertEqual('1.0.0', plugin.version)
        finally:
            if controller is not None:
                controller.stop()
            PluginControllerTest._destroy_plugin('P1')
Beispiel #14
0
    def test_ventilation_plugin_anti_ping_pong(self):
        # This test will see if the gateway will not keep sending events back and forth when an event change happens
        # This can be caused by ping-ponging back and forth between the plugin and gateway when sending updates
        plugin = Plugin(id=2, name='dummy', version='0.0.1')

        def get_ventilation(id):
            return Ventilation(id=id,
                               amount_of_levels=4,
                               source='plugin',
                               plugin=plugin)

        with mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \
                mock.patch.object(Ventilation, 'select', return_value=[get_ventilation(43)]):

            events = []

            def callback(event, self=self):
                events.append(event)
                if len(events) > 20:
                    self.fail(
                        'There should never be more than 20 events due to ventilation in this test'
                    )
                # resend the same event to mock the plugin who will send an event back with the same status
                # id, mode, level=None, timer=None, remaining_time=None, last_seen=None
                status_dto = VentilationStatusDTO(
                    id=event.data['id'],
                    mode=event.data['mode'],
                    level=event.data['level'],
                    remaining_time=event.data['timer'],
                )
                self.controller.set_status(status_dto)
                self.pubsub._publish_all_events()

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE,
                                                 callback)

            # event that ventilation box is running in automatic mode
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))

            # Clear all current events
            events = []

            # event that timer has been started
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=1,
                                     timer=30,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertGreaterEqual(10, len(events))

            # event that timer is running
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=1,
                                     timer=None,
                                     remaining_time=15,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertGreaterEqual(10, len(events))

            # event that timer is done
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertGreaterEqual(10, len(events))
Beispiel #15
0
    def test_ventilation_timer_expire_automatic(self):
        plugin = Plugin(id=2, name='dummy', version='0.0.1')

        def get_ventilation(id):
            return Ventilation(id=id,
                               amount_of_levels=4,
                               source='plugin',
                               plugin=plugin)

        with mock.patch.object(Select, 'count', return_value=1), \
                mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \
                mock.patch.object(Ventilation, 'select',
                                  return_value=[get_ventilation(43)]):
            events = []

            def callback(event):
                events.append(event)

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE,
                                                 callback)

            # event that ventilation box is running in automatic mode
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(
                None, events[-1].data['remaining_time'])  # no timers running
            self.assertEqual(None,
                             events[-1].data['timer'])  # no timers running

            # Clear all current events
            events = []

            # event that timer has been started
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=30,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(
                None, events[-1].data['remaining_time']
            )  # There has not been an update from the ventilation box or plugin
            self.assertEqual(30, events[-1].data['timer'])

            for i in range(30, 0, -1):
                # Clear all current events
                events = []

                # event from ventilation plugin
                mode = 'automatic' if i % 2 == 0 else 'manual'
                self.controller.set_status(
                    VentilationStatusDTO(43,
                                         mode,
                                         level=1,
                                         timer=None,
                                         remaining_time=i,
                                         last_seen=time.time()))
                self.pubsub._publish_all_events()

                print(events)
                self.assertEqual(1, len(events))
                self.assertEqual(1, len(self.controller._status))
                self.assertEqual(i, events[-1].data['remaining_time'])
                self.assertEqual(30, events[-1].data['timer']
                                 )  # this value should be kept in cache

            # Clear all current events
            events = []

            # event from ventilation plugin -> Timer has expired, and has switched to automatic mode
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(None, events[-1].data['remaining_time'])
            self.assertEqual(
                None, events[-1].data['timer']
            )  # this value should now be cleared when timer has done
Beispiel #16
0
    def test_ventilation_timer_expire_manual(self):
        plugin = Plugin(id=2, name='dummy', version='0.0.1')

        def get_ventilation(id):
            return Ventilation(id=id,
                               amount_of_levels=4,
                               source='plugin',
                               plugin=plugin)

        with mock.patch.object(Select, 'count', return_value=1), \
                mock.patch.object(Ventilation, 'get', side_effect=get_ventilation), \
                mock.patch.object(Ventilation, 'select',
                                  return_value=[get_ventilation(43)]):
            events = []

            def callback(event):
                events.append(event)

            self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.STATE,
                                                 callback)

            # first timer is running
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=2,
                                     timer=60.0,
                                     remaining_time=5.0,
                                     last_seen=(time.time() - 10)))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))

            # This should not trigger an event
            self.controller._check_connected_timeout()
            # This should trigger an update event.
            self.controller._periodic_event_update()
            self.pubsub._publish_all_events()
            self.assertEqual(2, len(events))
            self.assertEqual(1, len(self.controller._status))

            # Clear all current events
            events = []

            # event that timer has been done
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(None, events[-1].data['remaining_time'])
            self.assertEqual(None, events[-1].data['timer'])

            # Clear all current events
            events = []

            # event that timer has been started
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=30,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(None, events[-1].data['remaining_time'])
            self.assertEqual(30, events[-1].data['timer'])

            # Clear all current events
            events = []

            # event from ventilation plugin
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=1,
                                     timer=None,
                                     remaining_time=29,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(29, events[-1].data['remaining_time'])
            self.assertEqual(
                30,
                events[-1].data['timer'])  # this value should be kept in cache

            # Clear all current events
            events = []

            # event from ventilation plugin
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=15,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(15, events[-1].data['remaining_time']
                             )  # this value should update from the event
            self.assertEqual(
                30,
                events[-1].data['timer'])  # this value should be kept in cache

            # Clear all current events
            events = []

            # event from ventilation plugin (same value)
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=15,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(0, len(events))
            self.assertEqual(1, len(self.controller._status))

            # event from ventilation plugin
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'automatic',
                                     level=1,
                                     timer=None,
                                     remaining_time=14,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(14, events[-1].data['remaining_time']
                             )  # this value should update from the event
            self.assertEqual(
                30,
                events[-1].data['timer'])  # this value should be kept in cache

            # Clear all current events
            events = []

            # event from ventilation plugin -> Timer has expired, but is still in manual mode
            self.controller.set_status(
                VentilationStatusDTO(43,
                                     'manual',
                                     level=1,
                                     timer=None,
                                     remaining_time=None,
                                     last_seen=time.time()))
            self.pubsub._publish_all_events()

            self.assertEqual(1, len(events))
            self.assertEqual(1, len(self.controller._status))
            self.assertEqual(None, events[-1].data['remaining_time'])
            self.assertEqual(
                None, events[-1].data['timer']
            )  # this value should now be cleared when timer has done