示例#1
0
 def test_one_minute_schedule(self):
     now_offset = 1577836800  # 2020
     minute = 60
     fakesleep.reset(seconds=now_offset)
     SchedulingController.TIMEZONE = 'Europe/Brussels'
     schedule = ScheduleDTO(id=1,
                            name='schedule',
                            start=0 * minute,
                            repeat='* * * * *',
                            duration=None,
                            end=now_offset + 60 * minute,
                            action='GROUP_ACTION',
                            arguments=1,
                            status='ACTIVE')
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertFalse(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 1 * minute, schedule.next_execution)
     time.sleep(1 * minute)
     self.assertTrue(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 2 * minute, schedule.next_execution)
     time.sleep(1 * minute)
     self.assertTrue(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 3 * minute, schedule.next_execution)
示例#2
0
 def test_midnight_crossover(self):
     now_offset = 1615939080  # 16/03/21 23:58
     minute = 60
     fakesleep.reset(seconds=now_offset
                     )  # Tricks the system to be in the time we specified
     SchedulingController.TIMEZONE = 'Europe/Brussels'
     schedule = ScheduleDTO(id=1,
                            name='schedule',
                            start=0 * minute,
                            repeat='* * * * *',
                            duration=None,
                            end=now_offset + 10 * minute,
                            action='GROUP_ACTION',
                            arguments=1,
                            status='ACTIVE')
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertFalse(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 1 * minute, schedule.next_execution)
     time.sleep(1 * minute)
     self.assertTrue(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 2 * minute, schedule.next_execution)
     time.sleep(1 * minute)
     self.assertTrue(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 3 * minute, schedule.next_execution)
示例#3
0
    def __get_controller(self, callback=None, action_timeout=60):
        """ Get a UserController using FILE. """
        if callback == None:
            self.__actions = []
            callback = self.__actions.append

        controller = SchedulingController(SchedulingControllerTest.FILE,
                                          callback, action_timeout)
        controller.start()
        return controller
示例#4
0
 def _get_controller(self):
     SetUpTestInjections(scheduling_db=self._db,
                         scheduling_db_lock=Lock(),
                         gateway_api=GatewayApi(),
                         user_controller=None,
                         maintenance_controller=None,
                         message_client=None,
                         configuration_controller=None)
     controller = SchedulingController()
     SetUpTestInjections(scheduling_controller=controller)
     controller.set_webinterface(WebInterface())
     return controller
示例#5
0
 def test_schedule_is_due(self):
     now_offset = 1577836800  # 2020-01-01
     offset_2018 = 1514764800  # 2018-01-01
     minute = 60
     hour = 60 * minute
     fakesleep.reset(seconds=offset_2018)
     SchedulingController.TIMEZONE = 'Europe/Brussels'
     schedule = ScheduleDTO(id=1,
                            name='schedule',
                            start=offset_2018,
                            repeat='0 * * * *',
                            duration=None,
                            end=now_offset + 24 * hour,
                            action='GROUP_ACTION',
                            arguments=1,
                            status='ACTIVE')
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertFalse(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(SchedulingController.NO_NTP_LOWER_LIMIT + 1 * hour,
                      schedule.next_execution)
     time.sleep(1 * hour)
     self.assertFalse(schedule.is_due)  # Date is before 2019
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(SchedulingController.NO_NTP_LOWER_LIMIT + 1 * hour,
                      schedule.next_execution)
     fakesleep.reset(seconds=now_offset)
     self.assertFalse(schedule.is_due)  # Time jump is ignored
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 1 * hour, schedule.next_execution)
     time.sleep(1 * hour)
     self.assertTrue(schedule.is_due)
     schedule.next_execution = SchedulingController._get_next_execution(
         schedule)
     self.assertEqual(now_offset + 2 * hour, schedule.next_execution)
示例#6
0
    def _get_controller():
        def _do_group_action(group_action_id):
            SchedulingControllerTest.RETURN_DATA[
                'do_group_action'] = group_action_id
            return {}

        def _do_basic_action(action_type, action_number):
            SchedulingControllerTest.RETURN_DATA['do_basic_action'] = (
                action_type, action_number)
            return {}

        gateway_api = Mock()
        gateway_api.get_timezone = lambda: 'UTC'
        gateway_api.do_basic_action = _do_basic_action

        group_action_controller = Mock()
        group_action_controller.do_group_action = _do_group_action

        SetUpTestInjections(gateway_api=gateway_api,
                            user_controller=None,
                            maintenance_controller=None,
                            message_client=None,
                            configuration_controller=None,
                            thermostat_controller=None,
                            ventilation_controller=Mock(VentilationController),
                            shutter_controller=Mock(),
                            output_controller=Mock(),
                            room_controller=Mock(),
                            input_controller=Mock(),
                            sensor_controller=Mock(),
                            pulse_counter_controller=Mock(),
                            frontpanel_controller=Mock(),
                            group_action_controller=group_action_controller,
                            module_controller=Mock())
        controller = SchedulingController()
        SetUpTestInjections(scheduling_controller=controller)
        controller.set_webinterface(WebInterface())
        return controller
示例#7
0
    def test_edge_cases_cron(self):
        now_offset = 1616371020  # Date and time: Sunday, March 21, 2021 11:57:00 PM GMT
        minute = 60
        SchedulingController.TIMEZONE = 'Europe/Brussels'
        fakesleep.reset(seconds=now_offset)
        SchedulingController.TIMEZONE = 'Europe/Brussels'
        schedule = ScheduleDTO(
            id=1,
            name='schedule',
            start=200,  # Thursday, January 1, 1970 1:03:20 AM
            repeat='* * * * *',  # every minute
            duration=None,
            end=now_offset + 10 * minute,  # for 10 minuted
            action='GROUP_ACTION',
            arguments=1,
            status='ACTIVE')
        # Should be 1616371020 + 60 = 1616371080
        schedule.next_execution = SchedulingController._get_next_execution(
            schedule)
        self.assertFalse(schedule.is_due)
        # Should still be 1616371020 + 60 = 1616371080
        for i in range(1, 11):
            schedule.next_execution = SchedulingController._get_next_execution(
                schedule)
            self.assertEqual(now_offset + i * minute, schedule.next_execution)
            time.sleep(minute)
            self.assertTrue(schedule.is_due)

        # now testing end of month behaviour
        now_offset = 1617235020  # 2021-03-31 23:57:00
        fakesleep.reset(seconds=now_offset)
        schedule.end = now_offset + 10 * minute  # Update when the schedule should end
        for i in range(1, 11):
            schedule.next_execution = SchedulingController._get_next_execution(
                schedule)
            self.assertEqual(now_offset + i * minute, schedule.next_execution)
            time.sleep(minute)
            self.assertTrue(schedule.is_due)
示例#8
0
def main():
    """ Main function. """
    config = ConfigParser()
    config.read(constants.get_config_file())

    defaults = {
        'username': config.get('OpenMotics', 'cloud_user'),
        'password': config.get('OpenMotics', 'cloud_pass')
    }
    controller_serial_port = config.get('OpenMotics', 'controller_serial')
    passthrough_serial_port = config.get('OpenMotics', 'passthrough_serial')
    power_serial_port = config.get('OpenMotics', 'power_serial')
    gateway_uuid = config.get('OpenMotics', 'uuid')

    config_lock = threading.Lock()
    user_controller = UserController(constants.get_config_database_file(),
                                     config_lock, defaults, 3600)
    config_controller = ConfigurationController(
        constants.get_config_database_file(), config_lock)

    led_service = LedService()

    controller_serial = Serial(controller_serial_port, 115200)
    power_serial = RS485(Serial(power_serial_port, 115200, timeout=None))

    master_communicator = MasterCommunicator(controller_serial)

    if passthrough_serial_port:
        passthrough_serial = Serial(passthrough_serial_port, 115200)
        passthrough_service = PassthroughService(master_communicator,
                                                 passthrough_serial)
        passthrough_service.start()

    master_communicator.start(
    )  # A running master_communicator is required for the startup of services below

    power_controller = PowerController(constants.get_power_database_file())
    power_communicator = PowerCommunicator(power_serial, power_controller)

    gateway_api = GatewayApi(master_communicator, power_communicator,
                             power_controller)

    scheduling_controller = SchedulingController(
        constants.get_scheduling_database_file(), config_lock, gateway_api)

    maintenance_service = MaintenanceService(
        gateway_api, constants.get_ssl_private_key_file(),
        constants.get_ssl_certificate_file())

    web_interface = WebInterface(user_controller, gateway_api,
                                 maintenance_service,
                                 led_service.in_authorized_mode,
                                 config_controller, scheduling_controller)

    scheduling_controller.set_webinterface(web_interface)

    plugin_controller = PluginController(web_interface, config_controller)

    web_interface.set_plugin_controller(plugin_controller)
    gateway_api.set_plugin_controller(plugin_controller)

    # Metrics
    metrics_cache_controller = MetricsCacheController(
        constants.get_metrics_database_file(), threading.Lock())
    metrics_collector = MetricsCollector(gateway_api)
    metrics_controller = MetricsController(plugin_controller,
                                           metrics_collector,
                                           metrics_cache_controller,
                                           config_controller, gateway_uuid)
    metrics_collector.set_controllers(metrics_controller, plugin_controller)
    metrics_collector.set_plugin_intervals(plugin_controller.metric_intervals)
    metrics_controller.add_receiver(metrics_controller.receiver)
    metrics_controller.add_receiver(web_interface.distribute_metric)

    plugin_controller.set_metrics_controller(metrics_controller)
    web_interface.set_metrics_collector(metrics_collector)
    web_interface.set_metrics_controller(metrics_controller)

    web_service = WebService(web_interface, config_controller)

    def _on_output(*args, **kwargs):
        metrics_collector.on_output(*args, **kwargs)
        gateway_api.on_outputs(*args, **kwargs)

    def _on_input(*args, **kwargs):
        metrics_collector.on_input(*args, **kwargs)
        gateway_api.on_inputs(*args, **kwargs)

    master_communicator.register_consumer(
        BackgroundConsumer(master_api.output_list(), 0, _on_output, True))
    master_communicator.register_consumer(
        BackgroundConsumer(master_api.input_list(), 0, _on_input))

    power_communicator.start()
    plugin_controller.start_plugins()
    metrics_controller.start()
    scheduling_controller.start()
    metrics_collector.start()
    web_service.start()

    led_thread = threading.Thread(target=led_driver,
                                  args=(led_service, master_communicator,
                                        power_communicator))
    led_thread.setName("Serial led driver thread")
    led_thread.daemon = True
    led_thread.start()

    def stop(signum, frame):
        """ This function is called on SIGTERM. """
        _ = signum, frame
        sys.stderr.write("Shutting down")
        web_service.stop()
        metrics_collector.stop()
        metrics_controller.stop()
        plugin_controller.stop()

    signal(SIGTERM, stop)
示例#9
0
 def _get_controller(self):
     gateway_api = GatewayApi()
     controller = SchedulingController(self._db, Lock(), gateway_api)
     controller.set_webinterface(WebInterface(None, gateway_api, None, None, None, controller))
     return controller
示例#10
0
 def _get_controller(self):
     gateway_api = GatewayApi()
     controller = SchedulingController(self._db, Lock(), gateway_api)
     controller.set_webinterface(
         WebInterface(None, gateway_api, None, None, None, controller))
     return controller
示例#11
0
def main():
    """ Main function. """
    log('Starting service...')

    config = ConfigParser()
    config.read(constants.get_config_file())

    defaults = {'username': config.get('OpenMotics', 'cloud_user'),
                'password': config.get('OpenMotics', 'cloud_pass')}
    controller_serial_port = config.get('OpenMotics', 'controller_serial')
    passthrough_serial_port = config.get('OpenMotics', 'passthrough_serial')
    power_serial_port = config.get('OpenMotics', 'power_serial')
    gateway_uuid = config.get('OpenMotics', 'uuid')

    config_lock = threading.Lock()
    user_controller = UserController(constants.get_config_database_file(), config_lock, defaults, 3600)
    config_controller = ConfigurationController(constants.get_config_database_file(), config_lock)

    dbus_service = DBusService('openmotics_service')

    controller_serial = Serial(controller_serial_port, 115200)
    power_serial = RS485(Serial(power_serial_port, 115200, timeout=None))

    master_communicator = MasterCommunicator(controller_serial)
    eeprom_controller = EepromController(
        EepromFile(master_communicator),
        EepromExtension(constants.get_eeprom_extension_database_file())
    )

    if passthrough_serial_port:
        passthrough_serial = Serial(passthrough_serial_port, 115200)
        passthrough_service = PassthroughService(master_communicator, passthrough_serial)
        passthrough_service.start()

    power_controller = PowerController(constants.get_power_database_file())
    power_communicator = PowerCommunicator(power_serial, power_controller)

    pulse_controller = PulseCounterController(
        constants.get_pulse_counter_database_file(),
        master_communicator,
        eeprom_controller
    )

    observer = Observer(master_communicator, dbus_service)
    gateway_api = GatewayApi(master_communicator, power_communicator, power_controller, eeprom_controller, pulse_controller, dbus_service, observer, config_controller)

    observer.set_gateway_api(gateway_api)

    scheduling_controller = SchedulingController(constants.get_scheduling_database_file(), config_lock, gateway_api)

    maintenance_service = MaintenanceService(gateway_api, constants.get_ssl_private_key_file(),
                                             constants.get_ssl_certificate_file())

    web_interface = WebInterface(user_controller, gateway_api, maintenance_service, dbus_service,
                                 config_controller, scheduling_controller)

    scheduling_controller.set_webinterface(web_interface)

    # Plugins
    plugin_controller = PluginController(web_interface, config_controller)
    web_interface.set_plugin_controller(plugin_controller)
    gateway_api.set_plugin_controller(plugin_controller)

    # Metrics
    metrics_cache_controller = MetricsCacheController(constants.get_metrics_database_file(), threading.Lock())
    metrics_collector = MetricsCollector(gateway_api, pulse_controller)
    metrics_controller = MetricsController(plugin_controller, metrics_collector, metrics_cache_controller, config_controller, gateway_uuid)
    metrics_collector.set_controllers(metrics_controller, plugin_controller)
    metrics_controller.add_receiver(metrics_controller.receiver)
    metrics_controller.add_receiver(web_interface.distribute_metric)

    plugin_controller.set_metrics_controller(metrics_controller)
    plugin_controller.set_metrics_collector(metrics_collector)
    web_interface.set_metrics_collector(metrics_collector)
    web_interface.set_metrics_controller(metrics_controller)

    web_service = WebService(web_interface, config_controller)
    plugin_controller.set_webservice(web_service)

    observer.subscribe_master(Observer.MasterEvents.INPUT_TRIGGER, metrics_collector.on_input)
    observer.subscribe_master(Observer.MasterEvents.INPUT_TRIGGER, plugin_controller.process_input_status)
    observer.subscribe_master(Observer.MasterEvents.ON_OUTPUTS, metrics_collector.on_output)
    observer.subscribe_master(Observer.MasterEvents.ON_OUTPUTS, plugin_controller.process_output_status)
    observer.subscribe_master(Observer.MasterEvents.ON_SHUTTER_UPDATE, plugin_controller.process_shutter_status)
    observer.subscribe_events(web_interface.process_observer_event)

    led_thread = threading.Thread(target=led_driver, args=(dbus_service, master_communicator, power_communicator))
    led_thread.setName("Serial led driver thread")
    led_thread.daemon = True
    led_thread.start()

    master_communicator.start()
    observer.start()
    power_communicator.start()
    metrics_controller.start()
    scheduling_controller.start()
    metrics_collector.start()
    web_service.start()
    gateway_api.start()
    plugin_controller.start()

    signal_request = {'stop': False}

    def stop(signum, frame):
        """ This function is called on SIGTERM. """
        _ = signum, frame
        log('Stopping service...')
        web_service.stop()
        metrics_collector.stop()
        metrics_controller.stop()
        plugin_controller.stop()
        log('Stopping service... Done')
        signal_request['stop'] = True

    signal(SIGTERM, stop)
    log('Starting service... Done')
    while not signal_request['stop']:
        time.sleep(1)