Example #1
0
    def extra_state_attributes(self) -> dict[str, Any] | None:
        """Return the state attributes of the device."""
        attr = {}

        if self.vera_device.has_battery:
            attr[ATTR_BATTERY_LEVEL] = self.vera_device.battery_level

        if self.vera_device.is_armable:
            armed = self.vera_device.is_armed
            attr[ATTR_ARMED] = "True" if armed else "False"

        if self.vera_device.is_trippable:
            last_tripped = self.vera_device.last_trip
            if last_tripped is not None:
                utc_time = utc_from_timestamp(int(last_tripped))
                attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat()
            else:
                attr[ATTR_LAST_TRIP_TIME] = None
            tripped = self.vera_device.is_tripped
            attr[ATTR_TRIPPED] = "True" if tripped else "False"

        power = self.vera_device.power
        if power:
            attr[ATTR_CURRENT_POWER_W] = convert(power, float, 0.0)

        energy = self.vera_device.energy
        if energy:
            attr[ATTR_CURRENT_ENERGY_KWH] = convert(energy, float, 0.0)

        attr["Vera Device Id"] = self.vera_device.vera_device_id

        return attr
Example #2
0
    def _parse_volume(cls, player_data):
        """Parse volume data to determine volume levels and mute state."""
        volume = {
            "level": 0,
            "step": 0,
            "muted": False,
        }

        try:
            volume_data = player_data["volume"]
            volume_muted = volume_data["is_muted"]
            volume_step = convert(volume_data["step"], int, 0)

            if volume_data["type"] == "db":
                level = convert(volume_data["value"], float, 0.0) / 80 * 100 + 100
            else:
                level = convert(volume_data["value"], float, 0.0)

            volume_level = convert(level, int, 0) / 100
        except KeyError:
            # catch KeyError
            pass
        else:
            volume["muted"] = volume_muted
            volume["step"] = volume_step
            volume["level"] = volume_level

        return volume
Example #3
0
    def _parse_now_playing(self, player_data):
        """Parse now playing data to determine title, artist, position, duration and artwork."""
        now_playing = {
            "title": None,
            "artist": None,
            "album": None,
            "position": 0,
            "duration": 0,
            "image": None,
        }
        now_playing_data = None

        try:
            now_playing_data = player_data["now_playing"]
            media_title = now_playing_data["three_line"]["line1"]
            media_artist = now_playing_data["three_line"]["line2"]
            media_album_name = now_playing_data["three_line"]["line3"]
            media_position = convert(now_playing_data["seek_position"], int, 0)
            media_duration = convert(now_playing_data.get("length"), int, 0)
            image_id = now_playing_data.get("image_key")
        except KeyError:
            # catch KeyError
            pass
        else:
            now_playing["title"] = media_title
            now_playing["artist"] = media_artist
            now_playing["album"] = media_album_name
            now_playing["position"] = media_position
            now_playing["duration"] = media_duration
            if image_id:
                now_playing["image"] = self._server.roonapi.get_image(image_id)

        return now_playing
Example #4
0
def closest(opp, *args):
    """Find closest entity.

    Closest to home:
        closest(states)
        closest(states.device_tracker)
        closest('group.children')
        closest(states.group.children)

    Closest to a point:
        closest(23.456, 23.456, 'group.children')
        closest('zone.school', 'group.children')
        closest(states.zone.school, 'group.children')

    As a filter:
        states | closest
        states.device_tracker | closest
        ['group.children', states.device_tracker] | closest
        'group.children' | closest(23.456, 23.456)
        states.device_tracker | closest('zone.school')
        'group.children' | closest(states.zone.school)

    """
    if len(args) == 1:
        latitude = opp.config.latitude
        longitude = opp.config.longitude
        entities = args[0]

    elif len(args) == 2:
        point_state = _resolve_state(opp, args[0])

        if point_state is None:
            _LOGGER.warning("Closest:Unable to find state %s", args[0])
            return None
        if not loc_helper.has_location(point_state):
            _LOGGER.warning(
                "Closest:State does not contain valid location: %s",
                point_state)
            return None

        latitude = point_state.attributes.get(ATTR_LATITUDE)
        longitude = point_state.attributes.get(ATTR_LONGITUDE)

        entities = args[1]

    else:
        latitude = convert(args[0], float)
        longitude = convert(args[1], float)

        if latitude is None or longitude is None:
            _LOGGER.warning("Closest:Received invalid coordinates: %s, %s",
                            args[0], args[1])
            return None

        entities = args[2]

    states = expand(opp, entities)

    # state will already be wrapped here
    return loc_helper.closest(latitude, longitude, states)
Example #5
0
def distance(opp, *args):
    """Calculate distance.

    Will calculate distance from home to a point or between points.
    Points can be passed in using state objects or lat/lng coordinates.
    """
    locations = []

    to_process = list(args)

    while to_process:
        value = to_process.pop(0)
        if isinstance(value, str) and not valid_entity_id(value):
            point_state = None
        else:
            point_state = _resolve_state(opp, value)

        if point_state is None:
            # We expect this and next value to be lat&lng
            if not to_process:
                _LOGGER.warning(
                    "Distance:Expected latitude and longitude, got %s", value)
                return None

            value_2 = to_process.pop(0)
            latitude = convert(value, float)
            longitude = convert(value_2, float)

            if latitude is None or longitude is None:
                _LOGGER.warning(
                    "Distance:Unable to process latitude and longitude: %s, %s",
                    value,
                    value_2,
                )
                return None

        else:
            if not loc_helper.has_location(point_state):
                _LOGGER.warning(
                    "Distance:State does not contain valid location: %s",
                    point_state)
                return None

            latitude = point_state.attributes.get(ATTR_LATITUDE)
            longitude = point_state.attributes.get(ATTR_LONGITUDE)

        locations.append((latitude, longitude))

    if len(locations) == 1:
        return opp.config.distance(*locations[0])

    return opp.config.units.length(
        loc_util.distance(*locations[0] + locations[1]), LENGTH_METERS)
Example #6
0
 def current_power_w(self):
     """Return the current power usage in W."""
     if "power" in self.fibaro_device.properties:
         power = self.fibaro_device.properties.power
         if power:
             return convert(power, float, 0.0)
     else:
         return None
Example #7
0
    def extra_state_attributes(self):
        """Return the state attributes of the device."""
        attr = {"fibaro_id": self.fibaro_device.id}

        try:
            if "battery" in self.fibaro_device.interfaces:
                attr[ATTR_BATTERY_LEVEL] = int(
                    self.fibaro_device.properties.batteryLevel)
            if "fibaroAlarmArm" in self.fibaro_device.interfaces:
                attr[ATTR_ARMED] = bool(self.fibaro_device.properties.armed)
            if "power" in self.fibaro_device.interfaces:
                attr[ATTR_CURRENT_POWER_W] = convert(
                    self.fibaro_device.properties.power, float, 0.0)
            if "energy" in self.fibaro_device.interfaces:
                attr[ATTR_CURRENT_ENERGY_KWH] = convert(
                    self.fibaro_device.properties.energy, float, 0.0)
        except (ValueError, KeyError):
            pass

        return attr
Example #8
0
def test_convert():
    """Test convert."""
    assert util.convert("5", int) == 5
    assert util.convert("5", float) == 5.0
    assert util.convert("True", bool) is True
    assert util.convert("NOT A NUMBER", int, 1) == 1
    assert util.convert(None, int, 1) == 1
    assert util.convert(object, int, 1) == 1
Example #9
0
def do_setup(opp, opp_config, config):
    """Run the setup after we have everything configured."""
    # Load calendars the user has configured
    opp.data[DATA_INDEX] = load_config(opp.config.path(YAML_DEVICES))

    calendar_service = GoogleCalendarService(opp.config.path(TOKEN_FILE))
    track_new_found_calendars = convert(config.get(CONF_TRACK_NEW), bool,
                                        DEFAULT_CONF_TRACK_NEW)
    setup_services(opp, opp_config, track_new_found_calendars,
                   calendar_service)

    for calendar in opp.data[DATA_INDEX].values():
        discovery.load_platform(opp, "calendar", DOMAIN, calendar, opp_config)

    # Look for any new calendars
    opp.services.call(DOMAIN, SERVICE_SCAN_CALENDARS, None)
    return True
Example #10
0
    def _update_hum_sensor(state):
        """Parse humidity sensor value."""
        _LOGGER.debug("Updating humidity sensor with value %s", state.state)

        # Return an error if the sensor change its state to Unknown.
        if state.state == STATE_UNKNOWN:
            _LOGGER.error(
                "Unable to parse humidity sensor %s, state: %s",
                state.entity_id,
                state.state,
            )
            return None

        unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
        hum = util.convert(state.state, float)

        if hum is None:
            _LOGGER.error(
                "Unable to parse humidity sensor %s, state: %s",
                state.entity_id,
                state.state,
            )
            return None

        if unit != PERCENTAGE:
            _LOGGER.error(
                "Humidity sensor %s has unsupported unit: %s %s",
                state.entity_id,
                unit,
                " (allowed: %)",
            )
            return None

        if hum > 100 or hum < 0:
            _LOGGER.error(
                "Humidity sensor %s is out of range: %s %s",
                state.entity_id,
                hum,
                "(allowed: 0-100%)",
            )
            return None

        return hum
Example #11
0
def setup_platform(opp, config, add_entities, discovery_info=None):
    """Display the current season."""
    if None in (opp.config.latitude, opp.config.longitude):
        _LOGGER.error("Latitude or longitude not set in Open Peer Power config")
        return False

    latitude = util.convert(opp.config.latitude, float)
    _type = config.get(CONF_TYPE)
    name = config.get(CONF_NAME)

    if latitude < 0:
        hemisphere = SOUTHERN
    elif latitude > 0:
        hemisphere = NORTHERN
    else:
        hemisphere = EQUATOR

    _LOGGER.debug(_type)
    add_entities([Season(opp, hemisphere, _type, name)])

    return True
Example #12
0
    def _update_temp_sensor(state):
        """Parse temperature sensor value."""
        _LOGGER.debug("Updating temp sensor with value %s", state.state)

        # Return an error if the sensor change its state to Unknown.
        if state.state == STATE_UNKNOWN:
            _LOGGER.error(
                "Unable to parse temperature sensor %s with state: %s",
                state.entity_id,
                state.state,
            )
            return None

        unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
        temp = util.convert(state.state, float)

        if temp is None:
            _LOGGER.error(
                "Unable to parse temperature sensor %s with state: %s",
                state.entity_id,
                state.state,
            )
            return None

        # convert to celsius if necessary
        if unit == TEMP_FAHRENHEIT:
            return util.temperature.fahrenheit_to_celsius(temp)
        if unit == TEMP_CELSIUS:
            return temp
        _LOGGER.error(
            "Temp sensor %s has unsupported unit: %s (allowed: %s, %s)",
            state.entity_id,
            unit,
            TEMP_CELSIUS,
            TEMP_FAHRENHEIT,
        )

        return None
Example #13
0
    def extra_state_attributes(self):
        """Return the state attributes of the device."""
        attr = {}
        if self.maker_params:
            # Is the maker sensor on or off.
            if self.maker_params["oppensor"]:
                # Note a state of 1 matches the WeMo app 'not triggered'!
                if self.maker_params["sensorstate"]:
                    attr[ATTR_SENSOR_STATE] = STATE_OFF
                else:
                    attr[ATTR_SENSOR_STATE] = STATE_ON

            # Is the maker switch configured as toggle(0) or momentary (1).
            if self.maker_params["switchmode"]:
                attr[ATTR_SWITCH_MODE] = MAKER_SWITCH_MOMENTARY
            else:
                attr[ATTR_SWITCH_MODE] = MAKER_SWITCH_TOGGLE

        if self.insight_params or (self.coffeemaker_mode is not None):
            attr[ATTR_CURRENT_STATE_DETAIL] = self.detail_state

        if self.insight_params:
            attr["on_latest_time"] = WemoSwitch.as_uptime(
                self.insight_params["onfor"])
            attr["on_today_time"] = WemoSwitch.as_uptime(
                self.insight_params["ontoday"])
            attr["on_total_time"] = WemoSwitch.as_uptime(
                self.insight_params["ontotal"])
            attr["power_threshold_w"] = (
                convert(self.insight_params["powerthreshold"], float, 0.0) /
                1000.0)

        if self.coffeemaker_mode is not None:
            attr[ATTR_COFFEMAKER_MODE] = self.coffeemaker_mode

        return attr
Example #14
0
    def update(self) -> None:
        """Update the state."""
        super().update()
        if self.vera_device.category == veraApi.CATEGORY_TEMPERATURE_SENSOR:
            self.current_value = self.vera_device.temperature

            vera_temp_units = self.vera_device.vera_controller.temperature_units

            if vera_temp_units == "F":
                self._temperature_units = TEMP_FAHRENHEIT
            else:
                self._temperature_units = TEMP_CELSIUS

        elif self.vera_device.category == veraApi.CATEGORY_LIGHT_SENSOR:
            self.current_value = self.vera_device.light
        elif self.vera_device.category == veraApi.CATEGORY_UV_SENSOR:
            self.current_value = self.vera_device.light
        elif self.vera_device.category == veraApi.CATEGORY_HUMIDITY_SENSOR:
            self.current_value = self.vera_device.humidity
        elif self.vera_device.category == veraApi.CATEGORY_SCENE_CONTROLLER:
            controller = cast(veraApi.VeraSceneController, self.vera_device)
            value = controller.get_last_scene_id(True)
            time = controller.get_last_scene_time(True)
            if time == self.last_changed_time:
                self.current_value = None
            else:
                self.current_value = value
            self.last_changed_time = time
        elif self.vera_device.category == veraApi.CATEGORY_POWER_METER:
            power = convert(self.vera_device.power, float, 0)
            self.current_value = int(round(power, 0))
        elif self.vera_device.is_trippable:
            tripped = self.vera_device.is_tripped
            self.current_value = "Tripped" if tripped else "Not Tripped"
        else:
            self.current_value = "Unknown"
Example #15
0
 def current_power_w(self):
     """Return the current power usage in W."""
     if "power" in self.fibaro_device.interfaces:
         return convert(self.fibaro_device.properties.power, float, 0.0)
     return None
Example #16
0
 def today_energy_kwh(self):
     """Return the today total energy usage in kWh."""
     if self.insight_params:
         miliwatts = convert(self.insight_params["todaymw"], float, 0.0)
         return round(miliwatts / (1000.0 * 1000.0 * 60), 2)
Example #17
0
 def current_power_w(self):
     """Return the current power usage in W."""
     if self.insight_params:
         return convert(self.insight_params["currentpower"], float,
                        0.0) / 1000.0
Example #18
0
    def _check_entity_ready(self):
        """Check if all required values are discovered and create entity."""
        if self._workaround_ignore:
            return
        if self._entity is not None:
            return

        for name in self._schema[const.DISC_VALUES]:
            if self._values[name] is None and not self._schema[
                    const.DISC_VALUES][name].get(const.DISC_OPTIONAL):
                return

        component = self._schema[const.DISC_COMPONENT]

        workaround_component = workaround.get_device_component_mapping(
            self.primary)
        if workaround_component and workaround_component != component:
            if workaround_component == workaround.WORKAROUND_IGNORE:
                _LOGGER.info(
                    "Ignoring Node %d Value %d due to workaround",
                    self.primary.node.node_id,
                    self.primary.value_id,
                )
                # No entity will be created for this value
                self._workaround_ignore = True
                return
            _LOGGER.debug("Using %s instead of %s", workaround_component,
                          component)
            component = workaround_component

        entity_id = self._registry.async_get_entity_id(
            component, DOMAIN, compute_value_unique_id(self._node,
                                                       self.primary))
        if entity_id is None:
            value_name = _value_name(self.primary)
            entity_id = generate_entity_id(component + ".{}", value_name, [])
        node_config = self._device_config.get(entity_id)

        # Configure node
        _LOGGER.debug(
            "Adding Node_id=%s Generic_command_class=%s, "
            "Specific_command_class=%s, "
            "Command_class=%s, Value type=%s, "
            "Genre=%s as %s",
            self._node.node_id,
            self._node.generic,
            self._node.specific,
            self.primary.command_class,
            self.primary.type,
            self.primary.genre,
            component,
        )

        if node_config.get(CONF_IGNORED):
            _LOGGER.info("Ignoring entity %s due to device settings",
                         entity_id)
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        polling_intensity = convert(node_config.get(CONF_POLLING_INTENSITY),
                                    int)
        if polling_intensity:
            self.primary.enable_poll(polling_intensity)

        platform = import_module(f".{component}", __name__)

        device = platform.get_device(node=self._node,
                                     values=self,
                                     node_config=node_config,
                                     opp=self._opp)
        if device is None:
            # No entity will be created for this value
            self._workaround_ignore = True
            return

        self._entity = device

        @callback
        def _on_ready(sec):
            _LOGGER.info(
                "Z-Wave entity %s (node_id: %d) ready after %d seconds",
                device.name,
                self._node.node_id,
                sec,
            )
            self._opp.async_add_job(discover_device, component, device)

        @callback
        def _on_timeout(sec):
            _LOGGER.warning(
                "Z-Wave entity %s (node_id: %d) not ready after %d seconds, "
                "continuing anyway",
                device.name,
                self._node.node_id,
                sec,
            )
            self._opp.async_add_job(discover_device, component, device)

        async def discover_device(component, device):
            """Put device in a dictionary and call discovery on it."""
            if self._opp.data[DATA_DEVICES].get(device.unique_id):
                return

            self._opp.data[DATA_DEVICES][device.unique_id] = device
            if component in PLATFORMS:
                async_dispatcher_send(self._opp, f"zwave_new_{component}",
                                      device)
            else:
                await discovery.async_load_platform(
                    self._opp,
                    component,
                    DOMAIN,
                    {const.DISCOVERY_DEVICE: device.unique_id},
                    self._zwave_config,
                )

        if device.unique_id:
            self._opp.add_job(discover_device, component, device)
        else:
            self._opp.add_job(check_has_unique_id, device, _on_ready,
                              _on_timeout)
Example #19
0
    def _finalize_start():
        """Perform final initializations after Z-Wave network is awaked."""
        polling_interval = convert(config.get(CONF_POLLING_INTERVAL), int)
        if polling_interval is not None:
            network.set_poll_interval(polling_interval, False)

        poll_interval = network.get_poll_interval()
        _LOGGER.info("Z-Wave polling interval set to %d ms", poll_interval)

        opp.bus.listen_once(EVENT_OPENPEERPOWER_STOP, stop_network)

        # Register node services for Z-Wave network
        opp.services.register(DOMAIN, const.SERVICE_ADD_NODE, add_node)
        opp.services.register(DOMAIN, const.SERVICE_ADD_NODE_SECURE,
                              add_node_secure)
        opp.services.register(DOMAIN, const.SERVICE_REMOVE_NODE, remove_node)
        opp.services.register(DOMAIN, const.SERVICE_CANCEL_COMMAND,
                              cancel_command)
        opp.services.register(DOMAIN, const.SERVICE_HEAL_NETWORK, heal_network)
        opp.services.register(DOMAIN, const.SERVICE_SOFT_RESET, soft_reset)
        opp.services.register(DOMAIN, const.SERVICE_TEST_NETWORK, test_network)
        opp.services.register(DOMAIN, const.SERVICE_STOP_NETWORK, stop_network)
        opp.services.register(DOMAIN,
                              const.SERVICE_RENAME_NODE,
                              rename_node,
                              schema=RENAME_NODE_SCHEMA)
        opp.services.register(DOMAIN,
                              const.SERVICE_RENAME_VALUE,
                              rename_value,
                              schema=RENAME_VALUE_SCHEMA)
        opp.services.register(
            DOMAIN,
            const.SERVICE_SET_CONFIG_PARAMETER,
            set_config_parameter,
            schema=SET_CONFIG_PARAMETER_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_SET_NODE_VALUE,
            set_node_value,
            schema=SET_NODE_VALUE_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_REFRESH_NODE_VALUE,
            refresh_node_value,
            schema=REFRESH_NODE_VALUE_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_PRINT_CONFIG_PARAMETER,
            print_config_parameter,
            schema=PRINT_CONFIG_PARAMETER_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_REMOVE_FAILED_NODE,
            remove_failed_node,
            schema=NODE_SERVICE_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_REPLACE_FAILED_NODE,
            replace_failed_node,
            schema=NODE_SERVICE_SCHEMA,
        )

        opp.services.register(
            DOMAIN,
            const.SERVICE_CHANGE_ASSOCIATION,
            change_association,
            schema=CHANGE_ASSOCIATION_SCHEMA,
        )
        opp.services.register(DOMAIN,
                              const.SERVICE_SET_WAKEUP,
                              set_wakeup,
                              schema=SET_WAKEUP_SCHEMA)
        opp.services.register(DOMAIN,
                              const.SERVICE_PRINT_NODE,
                              print_node,
                              schema=NODE_SERVICE_SCHEMA)
        opp.services.register(
            DOMAIN,
            const.SERVICE_REFRESH_ENTITY,
            async_refresh_entity,
            schema=REFRESH_ENTITY_SCHEMA,
        )
        opp.services.register(DOMAIN,
                              const.SERVICE_REFRESH_NODE,
                              refresh_node,
                              schema=NODE_SERVICE_SCHEMA)
        opp.services.register(
            DOMAIN,
            const.SERVICE_RESET_NODE_METERS,
            reset_node_meters,
            schema=RESET_NODE_METERS_SCHEMA,
        )
        opp.services.register(
            DOMAIN,
            const.SERVICE_SET_POLL_INTENSITY,
            set_poll_intensity,
            schema=SET_POLL_INTENSITY_SCHEMA,
        )
        opp.services.register(DOMAIN,
                              const.SERVICE_HEAL_NODE,
                              heal_node,
                              schema=HEAL_NODE_SCHEMA)
        opp.services.register(DOMAIN,
                              const.SERVICE_TEST_NODE,
                              test_node,
                              schema=TEST_NODE_SCHEMA)
Example #20
0
 def current_power_w(self) -> float | None:
     """Return the current power usage in W."""
     power = self.vera_device.power
     if power:
         return convert(power, float, 0.0)
Example #21
0
 def today_energy_kwh(self):
     """Return the today total energy usage in kWh."""
     if "energy" in self.fibaro_device.interfaces:
         return convert(self.fibaro_device.properties.energy, float, 0.0)
     return None