Example #1
0
class Event(object):
    class Types(object):
        OUTPUT = 'OUTPUT'
        INPUT = 'INPUT'
        SENSOR = 'SENSOR'
        THERMOSTAT = 'THERMOSTAT'
        SYSTEM = 'SYSTEM'
        POWER = 'POWER'
        BUTTON_PRESS = 'BUTTON_PRESS'
        LED_ON = 'LED_ON'
        LED_BLINK = 'LED_BLINK'
        UNKNOWN = 'UNKNOWN'

    class SensorType(object):
        TEMPERATURE = 'TEMPERATURE'
        HUMIDITY = 'HUMIDITY'
        BRIGHTNESS = 'BRIGHTNESS'
        UNKNOWN = 'UNKNOWN'

    class SystemEventTypes(object):
        EEPROM_ACTIVATE = 'EEPROM_ACTIVATE'
        ONBOARD_TEMP_CHANGED = 'ONBOARD_TEMP_CHANGED'
        UNKNOWN = 'UNKNOWN'

    class ThermostatOrigins(object):
        SLAVE = 'SLAVE'
        MASTER = 'MASTER'
        UNKNOWN = 'UNKNOWN'

    class Bus(object):
        RS485 = 'RS485'
        CAN = 'CAN'

    class Leds(object):
        LED_0 = 0
        LED_1 = 1
        LED_2 = 2
        LED_3 = 3
        LED_4 = 4
        LED_5 = 5
        LED_6 = 6
        LED_7 = 7
        LED_8 = 8
        LED_9 = 9
        LED_10 = 10
        LED_11 = 11
        LED_12 = 12
        LED_13 = 13
        LED_14 = 14
        LED_15 = 15

    class LedStates(object):
        OFF = 'OFF'
        ON = 'ON'

    class LedFrequencies(object):
        BLINKING_25 = 'BLINKING_25'
        BLINKING_50 = 'BLINKING_50'
        BLINKING_75 = 'BLINKING_75'
        SOLID = 'SOLID'

    class Buttons(object):
        SETUP = 0
        ACTION = 1
        CAN_POWER = 2
        SELECT = 3

    class ButtonStates(object):
        RELEASED = 0
        PRESSED = 1
        PRESSED_5S = 2
        PRESSED_LONG = 3

    def __init__(self, data):
        self._type = data['type']
        self._action = data['action']
        self._device_nr = data['device_nr']
        self._data = data['data']
        self._word_helper = WordField('')

    @property
    def type(self):
        type_map = {
            0: Event.Types.OUTPUT,
            1: Event.Types.INPUT,
            2: Event.Types.SENSOR,
            20: Event.Types.THERMOSTAT,
            250: Event.Types.BUTTON_PRESS,
            251: Event.Types.LED_BLINK,
            252: Event.Types.LED_ON,
            253: Event.Types.POWER,
            254: Event.Types.SYSTEM
        }
        return type_map.get(self._type, Event.Types.UNKNOWN)

    @property
    def data(self):
        if self.type == Event.Types.OUTPUT:
            timer_factor = None
            timer_value = self._word_decode(
                self._data[2:])  # type: Optional[int]
            if self._data[1] == 0:
                timer_value = None
            elif self._data[1] == 1:
                timer_factor = 0.1
            elif self._data[1] == 2:
                timer_factor = 1
            elif self._data[2] == 3:
                timer_factor = 60
            return {
                'output': self._device_nr,
                'status': self._action == 1,
                'dimmer_value': self._data[0],
                'timer_factor': timer_factor,
                'timer_value': timer_value
            }
        if self.type == Event.Types.INPUT:
            return {'input': self._device_nr, 'status': self._action == 1}
        if self.type == Event.Types.SENSOR:
            sensor_type = Event.SensorType.UNKNOWN
            sensor_value = None
            if self._action == 0:
                sensor_type = Event.SensorType.TEMPERATURE
                sensor_value = Temperature.system_value_to_temperature(
                    self._data[1])
            elif self._action == 1:
                sensor_type = Event.SensorType.HUMIDITY
                sensor_value = Humidity.system_value_to_humidity(self._data[1])
            elif self._action == 2:
                sensor_type = Event.SensorType.BRIGHTNESS
                sensor_value = self._word_decode(self._data[0:2])
            return {
                'sensor': self._device_nr,
                'type': sensor_type,
                'value': sensor_value
            }
        if self.type == Event.Types.THERMOSTAT:
            origin_map = {
                0: Event.ThermostatOrigins.SLAVE,
                1: Event.ThermostatOrigins.MASTER
            }
            return {
                'origin':
                origin_map.get(self._action, Event.ThermostatOrigins.UNKNOWN),
                'thermostat':
                self._device_nr,
                'mode':
                self._data[0],
                'setpoint':
                self._data[1]
            }
        if self.type == Event.Types.BUTTON_PRESS:
            return {'button': self._device_nr, 'state': self._data[0]}
        if self.type == Event.Types.LED_BLINK:
            word_25 = self._device_nr
            word_50 = self._word_decode(self._data[0:2])
            word_75 = self._word_decode(self._data[2:4])
            leds = {}
            for i in range(16):
                if word_25 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_25
                elif word_50 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_50
                elif word_75 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_75
                else:
                    leds[i] = Event.LedFrequencies.SOLID
            return {'chip': self._device_nr, 'leds': leds}
        if self.type == Event.Types.LED_ON:
            word_on = self._word_decode(self._data[0:2])
            leds = {}
            for i in range(16):
                leds[i] = Event.LedStates.ON if word_on & (
                    1 << i) else Event.LedStates.OFF
            return {'chip': self._device_nr, 'leds': leds}
        if self.type == Event.Types.POWER:
            return {
                'bus':
                Event.Bus.RS485 if self._device_nr == 0 else Event.Bus.CAN,
                'power': self._data[0 > 1]
            }
        if self.type == Event.Types.SYSTEM:
            type_map = {
                0: Event.SystemEventTypes.EEPROM_ACTIVATE,
                1: Event.SystemEventTypes.ONBOARD_TEMP_CHANGED
            }
            event_type = type_map.get(self._action,
                                      Event.SystemEventTypes.UNKNOWN)
            event_data = {'type': event_type}
            if event_type == Event.SystemEventTypes.ONBOARD_TEMP_CHANGED:
                event_data['temperature'] = self._data[0]
            return event_data
        return None

    def _word_decode(self, data):  # type: (List[int]) -> int
        return self._word_helper.decode(bytearray(data[0:2]))

    def __str__(self):
        return '{0} ({1})'.format(
            self.type,
            self.data if self.type != Event.Types.UNKNOWN else self._type)
Example #2
0
class Event(object):
    class Types(object):
        OUTPUT = 'OUTPUT'
        INPUT = 'INPUT'
        SENSOR = 'SENSOR'
        THERMOSTAT = 'THERMOSTAT'
        SYSTEM = 'SYSTEM'
        POWER = 'POWER'
        EXECUTED_BA = 'EXECUTED_BA'
        BUTTON_PRESS = 'BUTTON_PRESS'
        LED_ON = 'LED_ON'
        LED_BLINK = 'LED_BLINK'
        UCAN = 'UCAN'
        EXECUTE_GATEWAY_API = 'EXECUTE_GATEWAY_API'
        UNKNOWN = 'UNKNOWN'

    class OutputEventTypes(object):
        STATUS = 'STATUS'
        LOCKING = 'LOCKING'

    class UCANEventTypes(object):
        POWER_OUT_ERROR = 'POWER_OUT_ERROR'
        POWER_OUT_RESTORED = 'POWER_OUT_RESTORED'
        POWER_OUT_ON = 'POWER_OUT_ON'
        POWER_OUT_OFF = 'POWER_OUT_OFF'
        I2C_ERROR = 'I2C_ERROR'
        UNKNOWN = 'UNKNOWN'

    class SensorType(object):
        TEMPERATURE = 'TEMPERATURE'
        HUMIDITY = 'HUMIDITY'
        BRIGHTNESS = 'BRIGHTNESS'
        UNKNOWN = 'UNKNOWN'

    class SystemEventTypes(object):
        EEPROM_ACTIVATE = 'EEPROM_ACTIVATE'
        ONBOARD_TEMP_CHANGED = 'ONBOARD_TEMP_CHANGED'
        UNKNOWN = 'UNKNOWN'

    class ThermostatOrigins(object):
        SLAVE = 'SLAVE'
        MASTER = 'MASTER'
        UNKNOWN = 'UNKNOWN'

    class Bus(object):
        RS485 = 'RS485'
        CAN = 'CAN'

    class Leds(object):
        LED_0 = 0
        LED_1 = 1
        LED_2 = 2
        LED_3 = 3
        LED_4 = 4
        LED_5 = 5
        LED_6 = 6
        LED_7 = 7
        LED_8 = 8
        LED_9 = 9
        LED_10 = 10
        LED_11 = 11
        LED_12 = 12
        LED_13 = 13
        LED_14 = 14
        LED_15 = 15

    class LedStates(object):
        OFF = 'OFF'
        ON = 'ON'

    class LedFrequencies(object):
        BLINKING_25 = 'BLINKING_25'
        BLINKING_50 = 'BLINKING_50'
        BLINKING_75 = 'BLINKING_75'
        SOLID = 'SOLID'

    class Buttons(object):
        SETUP = 0
        ACTION = 1
        CAN_POWER = 2
        SELECT = 3

    class ButtonStates(object):
        RELEASED = 0
        PRESSED = 1
        PRESSED_5S = 2
        PRESSED_LONG = 3

    def __init__(self, data):
        self._type = data['type']
        self._action = data['action']
        self._device_nr = data['device_nr']
        self._data = data['data']
        self._word_helper = WordField('')
        self._address_helper = AddressField('', length=3)

    @property
    def type(self):
        type_map = {0: Event.Types.OUTPUT,
                    1: Event.Types.INPUT,
                    2: Event.Types.SENSOR,
                    20: Event.Types.THERMOSTAT,
                    21: Event.Types.UCAN,
                    22: Event.Types.EXECUTED_BA,
                    249: Event.Types.EXECUTE_GATEWAY_API,
                    250: Event.Types.BUTTON_PRESS,
                    251: Event.Types.LED_BLINK,
                    252: Event.Types.LED_ON,
                    253: Event.Types.POWER,
                    254: Event.Types.SYSTEM}
        return type_map.get(self._type, Event.Types.UNKNOWN)

    @property
    def data(self):
        if self.type == Event.Types.OUTPUT:
            data = {'output': self._device_nr}
            if self._action in [0, 1]:
                timer_type = self._data[1]  # type: int
                timer_value = self._word_decode(self._data[2:]) or 0  # type: int
                timer = Timer.event_timer_type_to_seconds(timer_type, timer_value)
                data.update({'type': Event.OutputEventTypes.STATUS,
                             'status': self._action == 1,
                             'dimmer_value': self._data[0],
                             'timer': timer})
            else:
                data.update({'type': Event.OutputEventTypes.LOCKING,
                             'locked': self._data[0] == 1})
            return data
        if self.type == Event.Types.INPUT:
            return {'input': self._device_nr,
                    'status': self._action == 1}
        if self.type == Event.Types.SENSOR:
            sensor_type = Event.SensorType.UNKNOWN
            sensor_value = None
            if self._action == 0:
                sensor_type = Event.SensorType.TEMPERATURE
                sensor_value = Temperature.system_value_to_temperature(self._data[1])
            elif self._action == 1:
                sensor_type = Event.SensorType.HUMIDITY
                sensor_value = Humidity.system_value_to_humidity(self._data[1])
            elif self._action == 2:
                sensor_type = Event.SensorType.BRIGHTNESS
                sensor_value = self._word_decode(self._data[0:2])
            return {'sensor': self._device_nr,
                    'type': sensor_type,
                    'value': sensor_value}
        if self.type == Event.Types.THERMOSTAT:
            origin_map = {0: Event.ThermostatOrigins.SLAVE,
                          1: Event.ThermostatOrigins.MASTER}
            return {'origin': origin_map.get(self._action, Event.ThermostatOrigins.UNKNOWN),
                    'thermostat': self._device_nr,
                    'mode': self._data[0],
                    'setpoint': self._data[1]}
        if self.type == Event.Types.BUTTON_PRESS:
            return {'button': self._device_nr,
                    'state': self._data[0]}
        if self.type == Event.Types.LED_BLINK:
            word_25 = self._device_nr
            word_50 = self._word_decode(self._data[0:2])
            word_75 = self._word_decode(self._data[2:4])
            leds = {}
            for i in range(16):
                if word_25 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_25
                elif word_50 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_50
                elif word_75 & (1 << i):
                    leds[i] = Event.LedFrequencies.BLINKING_75
                else:
                    leds[i] = Event.LedFrequencies.SOLID
            return {'chip': self._device_nr,
                    'leds': leds}
        if self.type == Event.Types.LED_ON:
            word_on = self._word_decode(self._data[0:2])
            leds = {}
            for i in range(16):
                leds[i] = Event.LedStates.ON if word_on & (1 << i) else Event.LedStates.OFF
            return {'chip': self._device_nr,
                    'leds': leds}
        if self.type == Event.Types.POWER:
            return {'bus': Event.Bus.RS485 if self._device_nr == 0 else Event.Bus.CAN,
                    'power': self._data[0 > 1]}
        if self.type == Event.Types.SYSTEM:
            type_map = {0: Event.SystemEventTypes.EEPROM_ACTIVATE,
                        1: Event.SystemEventTypes.ONBOARD_TEMP_CHANGED}
            event_type = type_map.get(self._action, Event.SystemEventTypes.UNKNOWN)
            event_data = {'type': event_type}
            if event_type == Event.SystemEventTypes.ONBOARD_TEMP_CHANGED:
                event_data['temperature'] = self._data[0]
            return event_data
        if self.type == Event.Types.UCAN:
            event_data = {'address': self._address_helper.decode(bytearray([self._device_nr & 0xFF]) + self._data[0:2])}
            if self._data[2] == 0 and self._data[3] == 0:
                event_data['type'] = Event.UCANEventTypes.POWER_OUT_ERROR
            elif self._data[2] == 0 and self._data[3] == 1:
                event_data['type'] = Event.UCANEventTypes.POWER_OUT_RESTORED
            elif self._data[2] == 0 and self._data[3] == 2:
                event_data['type'] = Event.UCANEventTypes.POWER_OUT_OFF
            elif self._data[2] == 2 and self._data[3] == 3:
                event_data['type'] = Event.UCANEventTypes.POWER_OUT_ON
            elif self._data[2] == 1:
                event_data.update({'type': Event.UCANEventTypes.I2C_ERROR,
                                   'i2c_address': self._data[3]})
            else:
                event_data.update({'type': Event.UCANEventTypes.UNKNOWN,
                                   'data': self._data[2:4]})
            return event_data
        if self.type == Event.Types.EXECUTED_BA:
            return {'basic_action': BasicAction(action_type=self._data[0],
                                                action=self._data[1],
                                                device_nr=self._device_nr,
                                                extra_parameter=self._word_decode(self._data[2:4]))}
        if self.type == Event.Types.EXECUTE_GATEWAY_API:
            return {'action': self._data[3],
                    'device_nr': self._device_nr,
                    'extra_parameter': self._word_decode(self._data[0:2])}
        return None

    def _word_decode(self, data):  # type: (List[int]) -> int
        return self._word_helper.decode(bytearray(data[0:2]))

    def __str__(self):
        return '{0} ({1})'.format(self.type, self.data if self.type != Event.Types.UNKNOWN else self._type)
Example #3
0
class BasicAction(object):
    def __init__(self,
                 action_type,
                 action,
                 device_nr=None,
                 extra_parameter=None
                 ):  # type: (int, int, Optional[int], Optional[int]) -> None
        self._word_helper = WordField('')
        self._byte_helper = ByteField('')
        self._action_type = self._byte_helper.encode(
            action_type)  # type: bytearray
        self._action = self._byte_helper.encode(action)  # type: bytearray
        self._device_nr = self._word_helper.encode(
            device_nr if device_nr is not None else 0)  # type: bytearray
        self._extra_parameter = self._word_helper.encode(
            extra_parameter
            if extra_parameter is not None else 0)  # type: bytearray

    @property
    def action_type(self):  # type: () -> int
        return self._byte_helper.decode(self._action_type)

    @property
    def action(self):  # type: () -> int
        return self._byte_helper.decode(self._action)

    @property
    def device_nr(self):  # type: () -> int
        return self._word_helper.decode(self._device_nr)

    @property
    def extra_parameter(self):  # type: () -> int
        return self._word_helper.decode(self._extra_parameter)

    def encode(self):  # type: () -> bytearray
        return self._action_type + self._action + self._device_nr + self._extra_parameter

    @property
    def in_use(self):  # type: () -> bool
        return self.action_type != 255 and self.action != 255

    @property
    def is_execute_group_action(self):  # type: () -> bool
        return self.action_type == 19 and self.action == 0

    @staticmethod
    def decode(data):  # type: (bytearray) -> BasicAction
        basic_action = BasicAction(action_type=data[0], action=data[1])
        basic_action._device_nr = data[2:4]
        basic_action._extra_parameter = data[4:6]
        return basic_action

    def __repr__(self):
        return 'BA({0},{1},{2},{3})'.format(self.action_type, self.action,
                                            self.device_nr,
                                            self.extra_parameter)

    def __eq__(self, other):  # type: (Any) -> bool
        if not isinstance(other, BasicAction):
            return False
        return self.encode() == other.encode()