Ejemplo n.º 1
0
    def test_address_mode(self):
        """ Test the address mode. """
        sad = power_api.set_addressmode()
        serial_mock = RS485(SerialMock(
            [sin(sad.create_input(power_api.BROADCAST_ADDRESS, 1, power_api.ADDRESS_MODE)),
             sout(power_api.want_an_address(power_api.POWER_API_8_PORTS).create_output(0, 0)),
             sin(power_api.set_address().create_input(0, 0, 1)),
             sout(power_api.want_an_address(power_api.POWER_API_12_PORTS).create_output(0, 0)),
             sin(power_api.set_address().create_input(0, 0, 2)),
             sout(''), ## Timeout read after 1 second
             sin(sad.create_input(power_api.BROADCAST_ADDRESS, 2, power_api.NORMAL_MODE))
            ], 1))

        controller = PowerController(PowerCommunicatorTest.FILE)
        comm = self.__get_communicator(serial_mock, power_controller=controller)
        comm.start()

        self.assertEqual(controller.get_free_address(), 1)

        comm.start_address_mode()
        self.assertTrue(comm.in_address_mode())
        time.sleep(0.5)
        comm.stop_address_mode()

        self.assertEqual(controller.get_free_address(), 3)
        self.assertFalse(comm.in_address_mode())
    def test_timekeeper(self):
        """ Test the TimeKeeper. """
        SetUpTestInjections(power_db=PowerCommunicatorTest.FILE)
        power_controller = PowerController()
        power_controller.register_power_module(1, power_api.POWER_MODULE)

        time_action = power_api.set_day_night(power_api.POWER_MODULE)
        times = [power_api.NIGHT for _ in range(8)]
        action = power_api.get_voltage(power_api.POWER_MODULE)

        serial_mock = RS485(
            SerialMock([
                sin(time_action.create_input(1, 1, *times)),
                sout(time_action.create_output(1, 1)),
                sin(action.create_input(1, 2)),
                sout(action.create_output(1, 2, 243))
            ], 1))

        comm = PowerCommunicatorTest._get_communicator(
            serial_mock, 1, power_controller=power_controller)
        comm.start()

        time.sleep(1.5)

        self.assertEquals((243, ), comm.do_command(1, action))
Ejemplo n.º 3
0
 def setUp(self):
     self.pubsub = PubSub()
     SetUpTestInjections(pubsub=self.pubsub)
     self.power_communicator = mock.Mock()
     SetUpTestInjections(power_communicator=self.power_communicator,
                         power_store=mock.Mock())
     self.controller = PowerController()
Ejemplo n.º 4
0
    def test_address_mode(self):
        """ Test the address mode. """
        sad = power_api.set_addressmode()
        serial_mock = RS485(SerialMock(
            [sin(sad.create_input(power_api.BROADCAST_ADDRESS, 1, power_api.ADDRESS_MODE)),
             sout(power_api.want_an_address(power_api.POWER_API_8_PORTS).create_output(0, 0)),
             sin(power_api.set_address().create_input(0, 0, 1)),
             sout(power_api.want_an_address(power_api.POWER_API_12_PORTS).create_output(0, 0)),
             sin(power_api.set_address().create_input(0, 0, 2)),
             sout(''),  # Timeout read after 1 second
             sin(sad.create_input(power_api.BROADCAST_ADDRESS, 2, power_api.NORMAL_MODE))],
            1
        ))
        SetUpTestInjections(power_db=PowerCommunicatorTest.FILE)

        controller = PowerController()
        comm = self.__get_communicator(serial_mock, power_controller=controller)
        comm.start()

        self.assertEqual(controller.get_free_address(), 1)

        comm.start_address_mode()
        self.assertTrue(comm.in_address_mode())
        time.sleep(0.5)
        comm.stop_address_mode()

        self.assertEqual(controller.get_free_address(), 3)
        self.assertFalse(comm.in_address_mode())
Ejemplo n.º 5
0
def main():
    """ The main function. """
    parser = argparse.ArgumentParser(description='Tool to bootload a power module.')
    parser.add_argument('--address', dest='address', type=int,
                        help='the address of the power module to bootload')
    parser.add_argument('--all', dest='all', action='store_true',
                        help='bootload all power modules')
    parser.add_argument('--file', dest='file',
                        help='the filename of the hex file to bootload')
    parser.add_argument('--8', dest='old', action='store_true',
                        help='bootload for the 8-port power modules')
    parser.add_argument('--version', dest='version', action='store_true',
                        help='display the version of the power module(s)')
    parser.add_argument('--verbose', dest='verbose', action='store_true',
                        help='show the serial output')

    args = parser.parse_args()

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

    port = config.get('OpenMotics', 'power_serial')
    power_serial = RS485(Serial(port, 115200))
    power_communicator = PowerCommunicator(power_serial, None, time_keeper_period=0,
                                           verbose=args.verbose)
    power_communicator.start()

    if args.address or args.all:
        power_controller = PowerController(constants.get_power_database_file())
        power_modules = power_controller.get_power_modules()
        if args.all:
            for module_id in power_modules:
                module = power_modules[module_id]
                addr = module['address']
                if args.version:
                    print "E%d - Version: %s" % (addr, version(addr, power_communicator))
                if args.file:
                    if args.old and module['version'] == POWER_API_8_PORTS:
                        bootload_8(addr, args.file, power_communicator)
                    elif not args.old and module['version'] == POWER_API_12_PORTS:
                        bootload_12(addr, args.file, power_communicator)

        else:
            addr = args.address
            modules = [module for module in power_modules if module['address'] == addr]
            if len(modules) != 1:
                print 'ERROR: Could not determine energy module version. Aborting'
                sys.exit(1)
            if args.version:
                print "E%d - Version: %s" % (addr, version(addr, power_communicator))
            if args.file:
                if args.old and module['version'] == POWER_API_8_PORTS:
                    bootload_8(addr, args.file, power_communicator)
                elif not args.old and module['version'] == POWER_API_12_PORTS:
                    bootload_12(addr, args.file, power_communicator)

    else:
        parser.print_help()
Ejemplo n.º 6
0
    def __get_communicator(self, serial_mock, time_keeper_period=0, address_mode_timeout=60,
                           power_controller=None):
        """ Get a PowerCommunicator. """
        if power_controller == None:
            power_controller = PowerController(PowerCommunicatorTest.FILE)

        return PowerCommunicator(serial_mock, power_controller,
                                 time_keeper_period=time_keeper_period,
                                 address_mode_timeout=address_mode_timeout)
Ejemplo n.º 7
0
    def test_timekeeper(self):
        """ Test the TimeKeeper. """
        power_controller = PowerController(PowerCommunicatorTest.FILE)
        power_controller.register_power_module(1, power_api.POWER_API_8_PORTS)

        time_action = power_api.set_day_night(power_api.POWER_API_8_PORTS)
        times = [power_api.NIGHT for _ in range(8)]
        action = power_api.get_voltage(power_api.POWER_API_8_PORTS)

        serial_mock = RS485(SerialMock(
            [sin(time_action.create_input(1, 1, *times)),
             sout(time_action.create_output(1, 1)),
             sin(action.create_input(1, 2)),
             sout(action.create_output(1, 2, 243))
            ], 1))

        comm = self.__get_communicator(serial_mock, 1, power_controller=power_controller)
        comm.start()

        time.sleep(1.5)

        self.assertEquals((243, ), comm.do_command(1, action))
Ejemplo n.º 8
0
def setup_minimal_power_platform():
    # type: () -> None
    config = ConfigParser()
    config.read(constants.get_config_file())
    power_serial_port = config.get('OpenMotics', 'power_serial')
    if power_serial_port:
        Injectable.value(power_db=constants.get_power_database_file())
        Injectable.value(power_store=PowerStore())
        Injectable.value(power_serial=RS485(
            Serial(power_serial_port, 115200, timeout=None)))
        Injectable.value(power_communicator=PowerCommunicator())
        Injectable.value(power_controller=PowerController())
        Injectable.value(p1_controller=P1Controller())
    else:
        Injectable.value(power_store=None)
        Injectable.value(power_communicator=None)
        Injectable.value(power_controller=None)
        Injectable.value(p1_controller=None)
        Injectable.value(power_serial=None)
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
 def __get_controller(self):
     """ Get a PowerController using FILE. """
     SetUpTestInjections(power_db=PowerControllerTest.FILE)
     return PowerController()
Ejemplo n.º 11
0
def main():
    """ The main function. """
    parser = argparse.ArgumentParser(
        description='Tool to bootload a power module.')
    parser.add_argument('--address',
                        dest='address',
                        type=int,
                        help='the address of the power module to bootload')
    parser.add_argument('--all',
                        dest='all',
                        action='store_true',
                        help='bootload all power modules')
    parser.add_argument('--file',
                        dest='file',
                        help='the filename of the hex file to bootload')
    parser.add_argument('--8',
                        dest='old',
                        action='store_true',
                        help='bootload for the 8-port power modules')
    parser.add_argument('--version',
                        dest='version',
                        action='store_true',
                        help='display the version of the power module(s)')
    parser.add_argument('--verbose',
                        dest='verbose',
                        action='store_true',
                        help='show the serial output')

    args = parser.parse_args()

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

    port = config.get('OpenMotics', 'power_serial')
    power_serial = RS485(Serial(port, 115200))
    power_communicator = PowerCommunicator(power_serial,
                                           None,
                                           time_keeper_period=0,
                                           verbose=args.verbose)
    power_communicator.start()

    if args.address or args.all:
        power_controller = PowerController(constants.get_power_database_file())
        power_modules = power_controller.get_power_modules()
        if args.all:
            for module_id in power_modules:
                module = power_modules[module_id]
                addr = module['address']
                if args.version:
                    print "E%d - Version: %s" % (
                        addr, version(addr, power_communicator))
                if args.file:
                    if args.old and module['version'] == POWER_API_8_PORTS:
                        bootload_8(addr,
                                   args.file,
                                   power_communicator,
                                   verbose=args.verbose)
                    elif not args.old and module[
                            'version'] == POWER_API_12_PORTS:
                        bootload_12(addr,
                                    args.file,
                                    power_communicator,
                                    verbose=args.verbose)

        else:
            addr = args.address
            modules = [
                module for module in power_modules.keys()
                if module['address'] == addr
            ]
            if len(modules) != 1:
                print 'ERROR: Could not determine energy module version. Aborting'
                sys.exit(1)
            if args.version:
                print "E%d - Version: %s" % (addr,
                                             version(addr, power_communicator))
            if args.file:
                if args.old and module['version'] == POWER_API_8_PORTS:
                    bootload_8(addr,
                               args.file,
                               power_communicator,
                               verbose=args.verbose)
                elif not args.old and module['version'] == POWER_API_12_PORTS:
                    bootload_12(addr,
                                args.file,
                                power_communicator,
                                verbose=args.verbose)

    else:
        parser.print_help()
Ejemplo n.º 12
0
class PowerControllerTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        SetTestMode()

    def setUp(self):
        self.pubsub = PubSub()
        SetUpTestInjections(pubsub=self.pubsub)
        self.power_communicator = mock.Mock()
        SetUpTestInjections(power_communicator=self.power_communicator,
                            power_store=mock.Mock())
        self.controller = PowerController()

    def test_get_module_current(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_current({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'CUR',
                                 '',
                                 '8f',
                                 module_type=bytearray(b'E')))
            ]

    def test_get_module_frequency(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_frequency({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'FRE',
                                 '',
                                 'f',
                                 module_type=bytearray(b'E')))
            ]

    def test_get_module_power(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_power({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'POW',
                                 '',
                                 '8f',
                                 module_type=bytearray(b'E')))
            ]

    def test_get_module_voltage(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_voltage({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'VOL',
                                 '',
                                 'f',
                                 module_type=bytearray(b'E')))
            ]

    def test_get_module_day_energy(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_day_energy({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'EDA',
                                 '',
                                 '8L',
                                 module_type=bytearray(b'E')))
            ]

    def test_get_module_night_energy(self):
        with mock.patch.object(self.power_communicator, 'do_command') as cmd:
            self.controller.get_module_night_energy({
                'version': POWER_MODULE,
                'address': '11.0'
            })
            assert cmd.call_args_list == [
                mock.call(
                    '11.0',
                    PowerCommand('G',
                                 'ENI',
                                 '',
                                 '8L',
                                 module_type=bytearray(b'E')))
            ]

    def test_config_event(self):
        events = []

        def handle_events(gateway_event):
            events.append(gateway_event)

        self.pubsub.subscribe_gateway_events(PubSub.GatewayTopics.CONFIG,
                                             handle_events)
        master_event = MasterEvent(MasterEvent.Types.POWER_ADDRESS_EXIT, {})
        self.pubsub.publish_master_event(PubSub.MasterTopics.POWER,
                                         master_event)
        self.pubsub._publish_all_events()

        assert GatewayEvent(GatewayEvent.Types.CONFIG_CHANGE,
                            {'type': 'powermodule'}) in events
        assert len(events) == 1
Ejemplo n.º 13
0
def setup_target_platform(target_platform, message_client_name):
    # type: (str, Optional[str]) -> None
    config = ConfigParser()
    config.read(constants.get_config_file())

    config_lock = Lock()
    metrics_lock = Lock()

    config_database_file = constants.get_config_database_file()

    # Debugging options
    try:
        debug_logger = config.get('OpenMotics', 'debug_logger')
        if debug_logger:
            logging.getLogger(debug_logger).setLevel(logging.DEBUG)
    except NoOptionError:
        pass

    # Webserver / Presentation layer
    try:
        https_port = int(config.get('OpenMotics', 'https_port'))
    except NoOptionError:
        https_port = 443
    try:
        http_port = int(config.get('OpenMotics', 'http_port'))
    except NoOptionError:
        http_port = 80
    Injectable.value(https_port=https_port)
    Injectable.value(http_port=http_port)
    Injectable.value(ssl_private_key=constants.get_ssl_private_key_file())
    Injectable.value(ssl_certificate=constants.get_ssl_certificate_file())

    # TODO: Clean up dependencies more to reduce complexity

    # IOC announcements
    # When below modules are imported, the classes are registerd in the IOC graph. This is required for
    # instances that are used in @Inject decorated functions below, and is also needed to specify
    # abstract implementations depending on e.g. the platform (classic vs core) or certain settings (classic
    # thermostats vs gateway thermostats)
    from plugins import base
    from gateway import (metrics_controller, webservice, scheduling, observer,
                         gateway_api, metrics_collector,
                         maintenance_controller, user_controller,
                         pulse_counter_controller, metrics_caching, watchdog,
                         output_controller, room_controller, sensor_controller,
                         shutter_controller, group_action_controller,
                         module_controller, ventilation_controller)
    from cloud import events
    _ = (metrics_controller, webservice, scheduling, observer, gateway_api,
         metrics_collector, maintenance_controller, base, events,
         user_controller, pulse_counter_controller, metrics_caching, watchdog,
         output_controller, room_controller, sensor_controller,
         shutter_controller, group_action_controller, module_controller,
         ventilation_controller)

    # IPC
    message_client = None
    if message_client_name is not None:
        message_client = MessageClient(message_client_name)
    Injectable.value(message_client=message_client)

    # Cloud API
    Injectable.value(gateway_uuid=config.get('OpenMotics', 'uuid'))

    try:
        parsed_url = urlparse(config.get('OpenMotics', 'vpn_check_url'))
    except NoOptionError:
        parsed_url = urlparse('')
    Injectable.value(cloud_endpoint=parsed_url.hostname)
    Injectable.value(cloud_port=parsed_url.port)
    Injectable.value(cloud_ssl=parsed_url.scheme == 'https')
    Injectable.value(cloud_api_version=0)

    cloud_url = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, '', '', '', ''))
    Injectable.value(cloud_url=cloud_url or None)

    try:
        firmware_url = config.get('OpenMotics', 'firmware_url')
    except NoOptionError:
        path = '/portal/firmware_metadata'
        firmware_url = urlunparse(
            (parsed_url.scheme, parsed_url.netloc, path, '', '', ''))
    Injectable.value(firmware_url=firmware_url or None)

    # User Controller
    Injectable.value(user_db=config_database_file)
    Injectable.value(user_db_lock=config_lock)
    Injectable.value(token_timeout=3600)
    Injectable.value(
        config={
            'username': config.get('OpenMotics', 'cloud_user'),
            'password': config.get('OpenMotics', 'cloud_pass')
        })

    # Metrics Controller
    Injectable.value(metrics_db=constants.get_metrics_database_file())
    Injectable.value(metrics_db_lock=metrics_lock)

    # Energy Controller
    try:
        power_serial_port = config.get('OpenMotics', 'power_serial')
    except NoOptionError:
        power_serial_port = ''
    if power_serial_port:
        Injectable.value(power_db=constants.get_power_database_file())
        Injectable.value(power_store=PowerStore())
        # TODO: make non blocking?
        Injectable.value(power_serial=RS485(
            Serial(power_serial_port, 115200, timeout=None)))
        Injectable.value(power_communicator=PowerCommunicator())
        Injectable.value(power_controller=PowerController())
        Injectable.value(p1_controller=P1Controller())
    else:
        Injectable.value(power_serial=None)
        Injectable.value(power_store=None)
        Injectable.value(
            power_communicator=None)  # TODO: remove from gateway_api
        Injectable.value(power_controller=None)
        Injectable.value(p1_controller=None)

    # Pulse Controller
    Injectable.value(pulse_db=constants.get_pulse_counter_database_file())

    # Master Controller
    try:
        controller_serial_port = config.get('OpenMotics', 'controller_serial')
    except NoOptionError:
        controller_serial_port = ''

    if controller_serial_port:
        Injectable.value(controller_serial=Serial(
            controller_serial_port, 115200, exclusive=True))
    if target_platform in [Platform.Type.DUMMY, Platform.Type.ESAFE]:
        Injectable.value(maintenance_communicator=None)
        Injectable.value(passthrough_service=None)
        Injectable.value(master_controller=MasterDummyController())
        Injectable.value(eeprom_db=None)
        from gateway.hal.master_controller_dummy import DummyEepromObject
        Injectable.value(eeprom_extension=DummyEepromObject())
    elif target_platform in Platform.CoreTypes:
        # FIXME don't create singleton for optional controller?
        from master.core import ucan_communicator, slave_communicator
        _ = ucan_communicator, slave_communicator
        core_cli_serial_port = config.get('OpenMotics', 'cli_serial')
        Injectable.value(cli_serial=Serial(core_cli_serial_port, 115200))
        Injectable.value(passthrough_service=None)  # Mark as "not needed"
        # TODO: Remove; should not be needed for Core
        Injectable.value(
            eeprom_db=constants.get_eeprom_extension_database_file())

        Injectable.value(master_communicator=CoreCommunicator())
        Injectable.value(
            maintenance_communicator=MaintenanceCoreCommunicator())
        Injectable.value(memory_file=MemoryFile())
        Injectable.value(master_controller=MasterCoreController())
    elif target_platform in Platform.ClassicTypes:
        # FIXME don't create singleton for optional controller?
        from master.classic import eeprom_extension
        _ = eeprom_extension
        leds_i2c_address = config.get('OpenMotics', 'leds_i2c_address')
        passthrough_serial_port = config.get('OpenMotics',
                                             'passthrough_serial')
        Injectable.value(
            eeprom_db=constants.get_eeprom_extension_database_file())
        Injectable.value(leds_i2c_address=int(leds_i2c_address, 16))
        if passthrough_serial_port:
            Injectable.value(
                passthrough_serial=Serial(passthrough_serial_port, 115200))
            from master.classic.passthrough import PassthroughService
            _ = PassthroughService  # IOC announcement
        else:
            Injectable.value(passthrough_service=None)
        Injectable.value(master_communicator=MasterCommunicator())
        Injectable.value(
            maintenance_communicator=MaintenanceClassicCommunicator())
        Injectable.value(master_controller=MasterClassicController())
    else:
        logger.warning('Unhandled master implementation for %s',
                       target_platform)

    if target_platform in [Platform.Type.DUMMY, Platform.Type.ESAFE]:
        Injectable.value(frontpanel_controller=None)
    elif target_platform in Platform.CoreTypes:
        Injectable.value(frontpanel_controller=FrontpanelCoreController())
    elif target_platform in Platform.ClassicTypes:
        Injectable.value(frontpanel_controller=FrontpanelClassicController())
    else:
        logger.warning('Unhandled frontpanel implementation for %s',
                       target_platform)

    # Thermostats
    thermostats_gateway_feature = Feature.get_or_none(
        name='thermostats_gateway')
    thermostats_gateway_enabled = thermostats_gateway_feature is not None and thermostats_gateway_feature.enabled
    if target_platform not in Platform.ClassicTypes or thermostats_gateway_enabled:
        Injectable.value(thermostat_controller=ThermostatControllerGateway())
    else:
        Injectable.value(thermostat_controller=ThermostatControllerMaster())
Ejemplo n.º 14
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')
    }

    user_controller = UserController(constants.get_user_database_file(),
                                     defaults, 3600)

    led_service = LedService()

    controller_serial_port = config.get('OpenMotics', 'controller_serial')
    passthrough_serial_port = config.get('OpenMotics', 'passthrough_serial')
    power_serial_port = config.get('OpenMotics', 'power_serial')

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

    master_communicator = MasterCommunicator(controller_serial)
    master_communicator.start()

    power_controller = PowerController(constants.get_power_database_file())

    power_communicator = PowerCommunicator(power_serial, power_controller)
    power_communicator.start()

    gateway_api = GatewayApi(master_communicator, power_communicator,
                             power_controller)

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

    passthrough_service = PassthroughService(master_communicator,
                                             passthrough_serial)
    passthrough_service.start()

    web_interface = WebInterface(user_controller, gateway_api,
                                 constants.get_scheduling_database_file(),
                                 maintenance_service,
                                 led_service.in_authorized_mode)

    plugin_controller = PluginController(web_interface)
    plugin_controller.start_plugins()

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

    web_service = WebService(web_interface)
    web_service.start()

    led_service.set_led('stat2', True)

    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. """
        sys.stderr.write("Shutting down")
        led_service.set_led('stat2', False)
        web_service.stop()

    signal(SIGTERM, stop)
Ejemplo n.º 15
0
 def __get_controller(self):
     """ Get a PowerController using FILE. """
     return PowerController(PowerControllerTest.FILE)
Ejemplo n.º 16
0
def main():
    """ The main function. """
    logger.info('Bootloader for Energy/Power Modules and P1 Concentrator')
    logger.info('Command: {0}'.format(' '.join(sys.argv)))

    parser = argparse.ArgumentParser(description='Tool to bootload a module.')
    parser.add_argument('--address',
                        dest='address',
                        type=int,
                        help='the address of the module to bootload')
    parser.add_argument('--all',
                        dest='all',
                        action='store_true',
                        help='bootload all modules')
    parser.add_argument('--file',
                        dest='file',
                        help='the filename of the hex file to bootload')
    parser.add_argument('--8',
                        dest='old',
                        action='store_true',
                        help='bootload for the 8-port power modules')
    parser.add_argument('--p1c',
                        dest='p1c',
                        action='store_true',
                        help='bootload for the P1 concentrator modules')
    parser.add_argument('--verbose',
                        dest='verbose',
                        action='store_true',
                        help='show the serial output')
    parser.add_argument('--scan',
                        dest='scan',
                        action='store_true',
                        help='Scan the energy bus for modules')

    args = parser.parse_args()

    if not args.file and not args.scan:
        parser.print_help()
        return

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

    port = config.get('OpenMotics', 'power_serial')
    power_serial = RS485(Serial(port, 115200))

    Injectable.value(power_serial=power_serial)
    Injectable.value(power_db=constants.get_power_database_file())

    power_controller = PowerController()
    power_communicator = PowerCommunicator(time_keeper_period=0,
                                           verbose=args.verbose)
    power_communicator.start()

    if args.scan:
        logger.info('Scanning addresses 0-255...')
        for address in xrange(256):
            for module_type, version in {
                    'E/P': power_api.ENERGY_MODULE,
                    'C': power_api.P1_CONCENTRATOR
            }.iteritems():
                try:
                    logger.info('{0}{1} - Version: {2}'.format(
                        module_type, address,
                        get_module_firmware_version(address, version,
                                                    power_communicator)))
                except Exception:
                    pass
        logger.info('Scan completed')
        return

    version = power_api.ENERGY_MODULE
    if args.old:
        version = power_api.POWER_MODULE
    elif args.p1c:
        version = power_api.P1_CONCENTRATOR

    def _bootload(_module, _module_address, filename):
        try:
            if version == _module['version'] == power_api.POWER_MODULE:
                bootload_power_module(_module_address, filename,
                                      power_communicator)
            elif version == _module['version'] == power_api.ENERGY_MODULE:
                bootload_energy_module(_module_address, filename,
                                       power_communicator)
            elif version == _module['version'] == power_api.P1_CONCENTRATOR:
                bootload_p1_concentrator(_module_address, filename,
                                         power_communicator)
        except CommunicationTimedOutException:
            logger.warning(
                'E{0} - Module unavailable. Skipping...'.format(address))
        except Exception:
            logger.exception(
                'E{0} - Unexpected exception during bootload. Skipping...'.
                format(address))

    if args.address or args.all:
        power_modules = power_controller.get_power_modules()
        if args.all:
            for module_id in power_modules:
                module = power_modules[module_id]
                address = module['address']
                _bootload(module, address, args.file)
        else:
            address = args.address
            modules = [
                module for module in power_modules.values()
                if module['address'] == address
            ]
            if len(modules) != 1:
                logger.info(
                    'ERROR: Cannot find a module with address {0}'.format(
                        address))
                sys.exit(0)
            module = modules[0]
            _bootload(module, address, args.file)
    else:
        parser.print_help()
Ejemplo n.º 17
0
def main():
    """ The main function. """
    logger.info('Energy/Power Module bootloader')
    logger.info('Command: {0}'.format(' '.join(sys.argv)))

    parser = argparse.ArgumentParser(
        description='Tool to bootload a power module.')
    parser.add_argument('--address',
                        dest='address',
                        type=int,
                        help='the address of the power module to bootload')
    parser.add_argument('--all',
                        dest='all',
                        action='store_true',
                        help='bootload all power modules')
    parser.add_argument('--file',
                        dest='file',
                        help='the filename of the hex file to bootload')
    parser.add_argument('--8',
                        dest='old',
                        action='store_true',
                        help='bootload for the 8-port power modules')
    parser.add_argument('--verbose',
                        dest='verbose',
                        action='store_true',
                        help='show the serial output')

    args = parser.parse_args()

    if not args.file:
        parser.print_help()
        return

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

    port = config.get('OpenMotics', 'power_serial')
    power_serial = RS485(Serial(port, 115200))

    Injectable.value(power_serial=power_serial)
    Injectable.value(power_db=constants.get_power_database_file())

    power_controller = PowerController()
    power_communicator = PowerCommunicator(time_keeper_period=0,
                                           verbose=args.verbose)
    power_communicator.start()

    def _bootload(_module, _module_address, filename, is_power_module):
        try:
            if is_power_module and _module['version'] == POWER_API_8_PORTS:
                bootload_8(_module_address, filename, power_communicator)
            elif not is_power_module and _module[
                    'version'] == POWER_API_12_PORTS:
                bootload_12(_module_address, filename, power_communicator)
        except CommunicationTimedOutException:
            logger.warning(
                'E{0} - Module unavailable. Skipping...'.format(address))
        except Exception:
            logger.exception(
                'E{0} - Unexpected exception during bootload. Skipping...'.
                format(address))

    if args.address or args.all:
        power_modules = power_controller.get_power_modules()
        if args.all:
            for module_id in power_modules:
                module = power_modules[module_id]
                address = module['address']
                _bootload(module, address, args.file, is_power_module=args.old)
        else:
            address = args.address
            modules = [
                module for module in power_modules.values()
                if module['address'] == address
            ]
            if len(modules) != 1:
                logger.info(
                    'ERROR: Cannot find a module with address {0}'.format(
                        address))
                sys.exit(0)
            module = modules[0]
            _bootload(module, address, args.file, is_power_module=args.old)
    else:
        parser.print_help()