Example #1
0
def main():
    """
    The main function runs a loop that waits for om bus calls, drives the leds and reads the
    switch.
    """
    try:
        logger.info('Starting led service...')
        config = ConfigParser()
        config.read(constants.get_config_file())
        i2c_address = int(config.get('OpenMotics', 'leds_i2c_address'), 16)

        led_controller = LedController(Hardware.get_i2c_device(), i2c_address,
                                       Hardware.get_gpio_input())
        led_controller.start()
        led_controller.set_led(Hardware.Led.POWER, True)

        signal_request = {'stop': False}

        def stop(signum, frame):
            """ This function is called on SIGTERM. """
            _ = signum, frame
            logger.info('Stopping led service...')
            led_controller.stop()
            logger.info('Stopping led service...Done')
            signal_request['stop'] = True

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

    except Exception as exception:
        logger.exception('Error starting led service: {0}'.format(exception))
Example #2
0
def main():
    """
    The main function runs a loop that waits for dbus calls, drives the leds and reads the
    switch.
    """
    try:
        config = ConfigParser()
        config.read(constants.get_config_file())
        i2c_address = int(config.get('OpenMotics', 'leds_i2c_address'), 16)

        led_controller = LedController(Hardware.get_i2c_device(), i2c_address, Hardware.get_gpio_input())
        led_controller.start()
        led_controller.set_led(Hardware.Led.POWER, True)

        DBusService('led_service',
                    event_receiver=lambda *args, **kwargs: led_controller.event_receiver(*args, **kwargs),
                    get_state=led_controller.get_state)

        LOGGER.log("Running led service.")
        mainloop = gobject.MainLoop()
        gobject.timeout_add(250, led_controller.drive_leds)
        gobject.timeout_add(250, led_controller.check_button)
        mainloop.run()
    except Exception as exception:
        LOGGER.log('Error starting led service: {0}'.format(exception))
Example #3
0
    def __init__(self, bus, path, i2c_device, i2c_address, input_button):
        dbus.service.Object.__init__(self, bus, path)
        self._i2c_device = i2c_device
        self._i2c_address = i2c_address
        self._input_button = input_button
        self._input_button_pressed_since = None

        self._network_enabled = False
        self._network_activity = False
        self._network_bytes = 0

        self._serial_activity = {4: False, 5: False}
        self._enabled_leds = {}
        self._previous_leds = {}
        self._last_i2c_led_code = 0

        self._authorized_mode = False
        self._authorized_timeout = 0

        self._check_states_thread = None

        self._gpio_led_config = Hardware.get_gpio_led_config()
        self._i2c_led_config = Hardware.get_i2c_led_config()
        for led in self._gpio_led_config.keys() + self._i2c_led_config.keys():
            self._enabled_leds[led] = False
            self._write_leds()
Example #4
0
def main():
    """
    The main function runs a loop that waits for dbus calls, drives the leds and reads the
    switch.
    """
    try:
        config = ConfigParser()
        config.read(constants.get_config_file())

        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

        system_bus = dbus.SystemBus()
        _ = dbus.service.BusName("com.openmotics.status",
                                 system_bus)  # Initializes the bus
        # The above `_ = dbus...` need to be there, or the bus won't be initialized

        i2c_device = Hardware.get_i2c_device()
        i2c_address = int(config.get('OpenMotics', 'leds_i2c_address'), 16)

        status = StatusObject(system_bus, '/com/openmotics/status', i2c_device,
                              i2c_address, Hardware.get_gpio_input())
        status.start()

        status.set_led(Hardware.Led.POWER, True)

        LOGGER.log("Running led service.")
        mainloop = gobject.MainLoop()

        gobject.timeout_add(250, status.drive_leds)
        gobject.timeout_add(250, status.check_button)

        mainloop.run()
    except Exception as exception:
        LOGGER.log('Error starting led service: {0}'.format(exception))
Example #5
0
    def __init__(self, i2c_device, i2c_address, input_button):
        self._i2c_device = i2c_device
        self._i2c_address = i2c_address
        self._input_button = input_button
        self._input_button_pressed_since = None
        self._input_button_released = True
        self._ticks = 0

        self._network_enabled = False
        self._network_activity = False
        self._network_bytes = 0

        self._serial_activity = {4: False, 5: False}
        self._enabled_leds = {}
        self._previous_leds = {}
        self._last_i2c_led_code = 0

        self._indicate_started = 0
        self._indicate_pointer = 0
        self._indicate_sequence = [True, False, False, False]

        self._authorized_mode = False
        self._authorized_timeout = 0

        self._check_states_thread = None
        self._leds_thread = None
        self._button_thread = None

        self._last_run_i2c = 0
        self._last_run_gpio = 0
        self._last_state_check = 0
        self._last_button_check = 0
        self._running = False

        self._message_client = MessageClient('led_service')
        self._message_client.add_event_handler(self.event_receiver)
        self._message_client.set_state_handler(self.get_state)

        self._gpio_led_config = Hardware.get_gpio_led_config()
        self._i2c_led_config = Hardware.get_i2c_led_config()
        for led in self._gpio_led_config.keys() + self._i2c_led_config.keys():
            self._enabled_leds[led] = False
            self._write_leds()
Example #6
0
    def __init__(self, i2c_device, i2c_address, input_button):
        self._i2c_device = i2c_device
        self._i2c_address = i2c_address
        self._input_button = input_button
        self._input_button_pressed_since = None
        self._input_button_released = True
        self._ticks = 0

        self._network_enabled = False
        self._network_activity = False
        self._network_bytes = 0

        self._serial_activity = {4: False, 5: False}
        self._enabled_leds = {}
        self._previous_leds = {}
        self._last_i2c_led_code = 0

        self._indicate_started = 0
        self._indicate_pointer = 0
        self._indicate_sequence = [True, False, False, False]

        self._authorized_mode = False
        self._authorized_timeout = 0

        self._check_states_thread = None

        self._last_run_i2c = 0
        self._last_run_gpio = 0
        self._last_state_check = 0
        self._last_button_check = 0

        self._gpio_led_config = Hardware.get_gpio_led_config()
        self._i2c_led_config = Hardware.get_i2c_led_config()
        for led in self._gpio_led_config.keys() + self._i2c_led_config.keys():
            self._enabled_leds[led] = False
            self._write_leds()
class FrontpanelController(object):

    INDICATE_TIMEOUT = 30
    AUTH_MODE_PRESS_DURATION = 5
    AUTH_MODE_TIMEOUT = 60
    BOARD_TYPE = Hardware.get_board_type()
    MAIN_INTERFACE = Hardware.get_main_interface()

    class Leds(object):
        EXPANSION = 'EXPANSION'
        STATUS_GREEN = 'STATUS_GREEN'
        STATUS_RED = 'STATUS_RED'
        CAN_STATUS_GREEN = 'CAN_STATUS_GREEN'
        CAN_STATUS_RED = 'CAN_STATUS_RED'
        CAN_COMMUNICATION = 'CAN_COMMUNICATION'
        P1 = 'P1'
        LAN_GREEN = 'LAN_GREEN'
        LAN_RED = 'LAN_RED'
        CLOUD = 'CLOUD'
        SETUP = 'SETUP'
        RELAYS_1_8 = 'RELAYS_1_8'
        RELAYS_9_16 = 'RELAYS_9_16'
        OUTPUTS_DIG_1_4 = 'OUTPUTS_DIG_1_4'
        OUTPUTS_DIG_5_7 = 'OUTPUTS_DIG_5_7'
        OUTPUTS_ANA_1_4 = 'OUTPUTS_ANA_1_4'
        INPUTS = 'INPUTS'
        POWER = 'POWER'
        ALIVE = 'ALIVE'
        VPN = 'VPN'
        COMMUNICATION_1 = 'COMMUNICATION_1'
        COMMUNICATION_2 = 'COMMUNICATION_2'

    class LedStates(object):
        OFF = 'OFF'
        BLINKING_25 = 'BLINKING_25'
        BLINKING_50 = 'BLINKING_50'
        BLINKING_75 = 'BLINKING_75'
        SOLID = 'SOLID'

    class Buttons(object):
        SELECT = 'SELECT'
        SETUP = 'SETUP'
        ACTION = 'ACTION'
        CAN_POWER = 'CAN_POWER'

    class ButtonStates(object):
        PRESSED = 'PRESSED'
        RELEASED = 'RELEASED'

    class SerialPorts(object):
        MASTER_API = 'MASTER_API'
        ENERGY = 'ENERGY'
        P1 = 'P1'

    @Inject
    def __init__(self,
                 master_controller=INJECTED,
                 power_communicator=INJECTED):
        # type: (MasterController, PowerCommunicator) -> None
        self._master_controller = master_controller
        self._power_communicator = power_communicator
        self._network_carrier = None
        self._network_activity = None
        self._network_activity_scan_counter = 0
        self._network_bytes = 0
        self._check_network_activity_thread = None
        self._authorized_mode = False
        self._authorized_mode_timeout = 0
        self._indicate = False
        self._indicate_timeout = 0
        self._master_stats = 0, 0
        self._power_stats = 0, 0

    @property
    def authorized_mode(self):
        # return Platform.get_platform() == Platform.Type.CORE_PLUS or self._authorized_mode  # Needed to validate Brain+ with no front panel attached
        return self._authorized_mode

    def event_receiver(self, event, payload):
        if event == OMBusEvents.CLOUD_REACHABLE:
            self._report_cloud_reachable(payload)
        elif event == OMBusEvents.VPN_OPEN:
            self._report_vpn_open(payload)
        elif event == OMBusEvents.CONNECTIVITY:
            self._report_connectivity(payload)

    def start(self):
        self._check_network_activity_thread = DaemonThread(
            name='frontpanel', target=self._do_frontpanel_tasks, interval=0.5)
        self._check_network_activity_thread.start()

    def stop(self):
        if self._check_network_activity_thread is not None:
            self._check_network_activity_thread.stop()

    def _report_carrier(self, carrier):
        # type: (bool) -> None
        raise NotImplementedError()

    def _report_connectivity(self, connectivity):
        # type: (bool) -> None
        raise NotImplementedError()

    def _report_network_activity(self, activity):
        # type: (bool) -> None
        raise NotImplementedError()

    def _report_serial_activity(self, serial_port, activity):
        # type: (str, Optional[bool]) -> None
        raise NotImplementedError()

    def _report_cloud_reachable(self, reachable):
        # type: (bool) -> None
        raise NotImplementedError()

    def _report_vpn_open(self, vpn_open):
        # type: (bool) -> None
        raise NotImplementedError()

    def indicate(self):
        self._indicate = True
        self._indicate_timeout = time.time(
        ) + FrontpanelController.INDICATE_TIMEOUT

    def _do_frontpanel_tasks(self):
        # Check network activity
        try:
            with open(
                    '/sys/class/net/{0}/carrier'.format(
                        FrontpanelController.MAIN_INTERFACE), 'r') as fh_up:
                line = fh_up.read()
            carrier = int(line) == 1
            carrier_changed = self._network_carrier != carrier
            if carrier_changed:
                self._network_carrier = carrier
                self._report_carrier(carrier)

            # Check network activity every second, or if the carrier changed
            if self._network_activity_scan_counter >= 9 or carrier_changed:
                self._network_activity_scan_counter = 0
                network_activity = False
                if self._network_carrier:  # There's no activity when there's no carrier
                    with open('/proc/net/dev', 'r') as fh_stat:
                        for line in fh_stat.readlines():
                            if FrontpanelController.MAIN_INTERFACE not in line:
                                continue
                            received, transmitted = 0, 0
                            parts = line.split()
                            if len(parts) == 17:
                                received = parts[1]
                                transmitted = parts[9]
                            elif len(parts) == 16:
                                (_, received) = tuple(parts[0].split(':'))
                                transmitted = parts[8]
                            new_bytes = received + transmitted
                            if self._network_bytes != new_bytes:
                                self._network_bytes = new_bytes
                                network_activity = True
                            else:
                                network_activity = False
                if self._network_activity != network_activity:
                    self._report_network_activity(network_activity)
                self._network_activity = network_activity
            self._network_activity_scan_counter += 1
        except Exception as exception:
            logger.error(
                'Error while checking network activity: {0}'.format(exception))

        # Monitor serial activity
        try:
            stats = self._master_controller.get_communication_statistics()
            new_master_stats = (stats['bytes_read'], stats['bytes_written'])
            activity = self._master_stats[0] != new_master_stats[
                0] or self._master_stats[1] != new_master_stats[1]
            self._report_serial_activity(
                FrontpanelController.SerialPorts.MASTER_API, activity)
            self._master_stats = new_master_stats

            if self._power_communicator is None:
                new_power_stats = 0, 0
            else:
                stats = self._power_communicator.get_communication_statistics()
                new_power_stats = (stats['bytes_read'], stats['bytes_written'])
            activity = self._power_stats[0] != new_power_stats[
                0] or self._power_stats[1] != new_power_stats[1]
            self._report_serial_activity(
                FrontpanelController.SerialPorts.ENERGY, activity)
            self._power_stats = new_power_stats

            activity = None  # type: Optional[bool]  # TODO: Load P1/RS232 activity
            self._report_serial_activity(FrontpanelController.SerialPorts.P1,
                                         activity)
        except Exception as exception:
            logger.error(
                'Error while checking serial activity: {0}'.format(exception))

        # Clear indicate timeout
        if time.time() > self._indicate_timeout:
            self._indicate = False
Example #8
0
class FrontpanelClassicController(FrontpanelController):

    IOCTL_I2C_SLAVE = 0x0703
    BOARD_TYPE = Hardware.get_board_type()
    ACTION_BUTTON_GPIO = 38 if BOARD_TYPE == Hardware.BoardType.BB else 26
    BUTTON = FrontpanelController.Buttons.ACTION
    AUTH_MODE_LEDS = [
        FrontpanelController.Leds.ALIVE, FrontpanelController.Leds.CLOUD,
        FrontpanelController.Leds.VPN,
        FrontpanelController.Leds.COMMUNICATION_1,
        FrontpanelController.Leds.COMMUNICATION_2
    ]
    if not BOARD_TYPE == Hardware.BoardType.BB:
        GPIO_LED_CONFIG = {
            FrontpanelController.Leds.POWER: 60,
            FrontpanelController.Leds.STATUS_RED: 48
        }
        I2C_LED_CONFIG = {
            FrontpanelController.Leds.COMMUNICATION_1: 64,
            FrontpanelController.Leds.COMMUNICATION_2: 128,
            FrontpanelController.Leds.VPN: 16,
            FrontpanelController.Leds.ALIVE: 1,
            FrontpanelController.Leds.CLOUD: 4
        }
    else:
        GPIO_LED_CONFIG = {
            FrontpanelController.Leds.POWER: 75,
            FrontpanelController.Leds.STATUS_RED: 60,
            FrontpanelController.Leds.ALIVE: 49
        }
        I2C_LED_CONFIG = {
            FrontpanelController.Leds.COMMUNICATION_1: 64,
            FrontpanelController.Leds.COMMUNICATION_2: 128,
            FrontpanelController.Leds.VPN: 16,
            FrontpanelController.Leds.CLOUD: 4
        }
    I2C_DEVICE = '/dev/i2c-2' if BOARD_TYPE == Hardware.BoardType.BB else '/dev/i2c-1'
    ALL_LEDS = [
        FrontpanelController.Leds.POWER, FrontpanelController.Leds.STATUS_RED,
        FrontpanelController.Leds.COMMUNICATION_1,
        FrontpanelController.Leds.COMMUNICATION_2,
        FrontpanelController.Leds.VPN, FrontpanelController.Leds.ALIVE,
        FrontpanelController.Leds.CLOUD
    ]
    BLINK_SEQUENCE = {
        FrontpanelController.LedStates.OFF: [],
        FrontpanelController.LedStates.BLINKING_25: [0],
        FrontpanelController.LedStates.BLINKING_50: [0, 1],
        FrontpanelController.LedStates.BLINKING_75: [0, 1, 2],
        FrontpanelController.LedStates.SOLID: [0, 1, 2, 3]
    }

    @Inject
    def __init__(self, leds_i2c_address=INJECTED):  # type: (int) -> None
        super(FrontpanelClassicController, self).__init__()
        self._leds_i2c_address = leds_i2c_address
        self._button_states = {}  # type: Dict[str, bool]
        self._poll_button_thread = None
        self._write_leds_thread = None
        self._enabled_leds = {}  # type: Dict[str, str]
        self._previous_leds = {}  # type: Dict[str, bool]
        self._last_i2c_led_code = None  # type: Optional[int]
        self._button_pressed_since = None  # type: Optional[float]
        self._button_released = False
        self._blink_counter = 0

    def _poll_button(self):
        # Check new state
        with open(
                '/sys/class/gpio/gpio{0}/value'.format(
                    FrontpanelClassicController.ACTION_BUTTON_GPIO),
                'r') as fh_inp:
            line = fh_inp.read()
        button_pressed = int(line) == 0
        self._button_states[
            FrontpanelClassicController.BUTTON] = button_pressed

        # Check for authorized mode
        if not button_pressed:
            self._button_released = True
        if self._authorized_mode:
            if time.time() > self._authorized_mode_timeout or (
                    button_pressed and self._button_released):
                self._authorized_mode = False
        else:
            if button_pressed:
                self._button_released = False
                if self._button_pressed_since is None:
                    self._button_pressed_since = time.time()
                if time.time(
                ) - self._button_pressed_since > FrontpanelController.AUTH_MODE_PRESS_DURATION:
                    self._authorized_mode = True
                    self._authorized_mode_timeout = time.time(
                    ) + FrontpanelController.AUTH_MODE_TIMEOUT
                    self._button_pressed_since = None
            else:
                self._button_pressed_since = None

    def start(self):
        super(FrontpanelClassicController, self).start()
        # Enable power led
        self._enabled_leds[FrontpanelController.Leds.
                           POWER] = FrontpanelController.LedStates.SOLID
        # Start polling/writing threads
        self._poll_button_thread = DaemonThread(name='buttonpoller',
                                                target=self._poll_button,
                                                interval=0.25)
        self._poll_button_thread.start()
        self._write_leds_thread = DaemonThread(name='ledwriter',
                                               target=self._write_leds,
                                               interval=0.25)
        self._write_leds_thread.start()

    def stop(self):
        super(FrontpanelClassicController, self).stop()
        if self._poll_button_thread is not None:
            self._poll_button_thread.stop()
        if self._write_leds_thread is not None:
            self._write_leds_thread.stop()

    def _report_carrier(self, carrier):
        # type: (bool) -> None
        state = FrontpanelController.LedStates.OFF if carrier else FrontpanelController.LedStates.SOLID
        self._enabled_leds[FrontpanelController.Leds.STATUS_RED] = state

    def _report_connectivity(self, connectivity):
        # type: (bool) -> None
        pass  # No support for connectivity

    def _report_network_activity(self, activity):
        # type: (bool) -> None
        state = FrontpanelController.LedStates.BLINKING_50 if activity else FrontpanelController.LedStates.OFF
        self._enabled_leds[FrontpanelController.Leds.ALIVE] = state

    def _report_serial_activity(self, serial_port, activity):
        # type: (str, Optional[bool]) -> None
        led = {
            FrontpanelController.SerialPorts.ENERGY:
            FrontpanelController.Leds.COMMUNICATION_1,
            FrontpanelController.SerialPorts.MASTER_API:
            FrontpanelController.Leds.COMMUNICATION_2
        }.get(serial_port)
        if led is None:
            return
        state = FrontpanelController.LedStates.BLINKING_50 if activity else FrontpanelController.LedStates.OFF
        self._enabled_leds[led] = state

    def _report_cloud_reachable(self, reachable):
        # type: (bool) -> None
        state = FrontpanelController.LedStates.SOLID if reachable else FrontpanelController.LedStates.OFF
        self._enabled_leds[FrontpanelController.Leds.CLOUD] = state

    def _report_vpn_open(self, vpn_open):
        # type: (bool) -> None
        state = FrontpanelController.LedStates.SOLID if vpn_open else FrontpanelController.LedStates.OFF
        self._enabled_leds[FrontpanelController.Leds.VPN] = state

    def _write_leds(self):
        # Override for indicate
        if self._indicate:
            self._enabled_leds[
                FrontpanelController.Leds.
                STATUS_RED] = FrontpanelController.LedStates.BLINKING_25

        # Map blinking states
        current_leds = self._map_states()

        # Drive I2C leds
        try:
            code = 0x0
            for led in FrontpanelClassicController.I2C_LED_CONFIG:
                if current_leds.get(led, False) is True:
                    code |= FrontpanelClassicController.I2C_LED_CONFIG[led]
            if self._authorized_mode:
                # Light all leds in authorized mode
                for led in FrontpanelClassicController.AUTH_MODE_LEDS:
                    code |= FrontpanelClassicController.I2C_LED_CONFIG.get(
                        led, 0x0)
            code = (~code) & 0xFF

            # Push code if needed
            if code != self._last_i2c_led_code:
                self._last_i2c_led_code = code
                with open(FrontpanelClassicController.I2C_DEVICE, 'r+',
                          1) as i2c:
                    fcntl.ioctl(i2c,
                                FrontpanelClassicController.IOCTL_I2C_SLAVE,
                                self._leds_i2c_address)
                    i2c.write(chr(code))
        except Exception as ex:
            logger.error('Error while writing to i2c: {0}'.format(ex))

        # Drive GPIO leds
        try:
            for led in FrontpanelClassicController.GPIO_LED_CONFIG:
                on = current_leds.get(led, False)
                if self._previous_leds.get(led) != on:
                    self._previous_leds[led] = on
                    try:
                        gpio = FrontpanelClassicController.GPIO_LED_CONFIG[led]
                        with open('/sys/class/gpio/gpio{0}/value'.format(gpio),
                                  'w') as fh_s:
                            fh_s.write('1' if on else '0')
                    except IOError:
                        pass  # The GPIO doesn't exist or is read only
        except Exception as ex:
            logger.error('Error while writing to GPIO: {0}'.format(ex))

    def _map_states(self):  # type: () -> Dict[str, bool]
        current_leds = {}  # type: Dict[str, bool]
        for led in FrontpanelClassicController.ALL_LEDS:
            requested_state = self._enabled_leds.get(
                led, FrontpanelController.LedStates.OFF)
            if requested_state == FrontpanelController.LedStates.OFF:
                current_leds[led] = False
            else:
                current_leds[
                    led] = self._blink_counter in FrontpanelClassicController.BLINK_SEQUENCE[
                        requested_state]
        self._blink_counter += 1
        if self._blink_counter >= 4:
            self._blink_counter = 0
        return current_leds