Example #1
0
    async def async_step_profile(self, data: dict) -> dict:
        """Prompt the user to select a user profile."""
        errors = {}
        reauth_profile = (self.context.get(const.PROFILE)
                          if self.context.get("source") == SOURCE_REAUTH else
                          None)
        profile = data.get(const.PROFILE) or reauth_profile

        if profile:
            existing_entries = [
                config_entry
                for config_entry in self._async_current_entries() if slugify(
                    config_entry.data.get(const.PROFILE)) == slugify(profile)
            ]

            if reauth_profile or not existing_entries:
                new_data = {
                    **self._current_data,
                    **data, const.PROFILE: profile
                }
                self._current_data = {}
                return await self.async_step_finish(new_data)

            errors["base"] = "already_configured"

        return self.async_show_form(
            step_id="profile",
            data_schema=vol.Schema({vol.Required(const.PROFILE): str}),
            errors=errors,
        )
Example #2
0
 def get_devices_with_name(self, name: str) -> [any]:
     """Get devices by name."""
     result = []
     name_slug = slugify(name.replace(" ", "", 99))
     for device in self.devices.values():
         if slugify(device.name.replace(" ", "", 99)) == name_slug:
             result.append(device)
     if not result:
         raise Exception(f"No device with name {name}")
     return result
Example #3
0
    def __init__(self, opp, area_name, keypad, button):
        """Register callback for activity on the button."""
        name = f"{keypad.name}: {button.name}"
        self._opp = opp
        self._has_release_event = (button.button_type is not None
                                   and "RaiseLower" in button.button_type)
        self._id = slugify(name)
        self._keypad = keypad
        self._area_name = area_name
        self._button_name = button.name
        self._button = button
        self._event = "lutron_event"
        self._full_id = slugify(f"{area_name} {keypad.name}: {button.name}")

        button.subscribe(self.button_callback, None)
Example #4
0
    async def async_step_user(self,
                              user_input: dict[str, Any] | None = None
                              ) -> FlowResult:
        """Handle a flow initialized by the user."""
        self._errors = {}

        if user_input is not None:
            is_ok = await self._check_location(user_input[CONF_LONGITUDE],
                                               user_input[CONF_LATITUDE])
            if is_ok:
                name = slugify(user_input[CONF_NAME])
                if not self._name_in_configuration_exists(name):
                    return self.async_create_entry(title=user_input[CONF_NAME],
                                                   data=user_input)

                self._errors[CONF_NAME] = "name_exists"
            else:
                self._errors["base"] = "wrong_location"

        # If opp.config has the location set and is a valid coordinate the
        # default location is set as default values in the form
        if not smhi_locations(
                self.opp) and await self._openpeerpower_location_exists():
            return await self._show_config_form(
                name=HOME_LOCATION_NAME,
                latitude=self.opp.config.latitude,
                longitude=self.opp.config.longitude,
            )

        return await self._show_config_form()
Example #5
0
async def test_load_unload_entry(opp, geofency_client, webhook_id):
    """Test that the appropriate dispatch signals are added and removed."""
    url = f"/api/webhook/{webhook_id}"

    # Enter the Home zone
    req = await geofency_client.post(url, data=GPS_ENTER_HOME)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(GPS_ENTER_HOME["device"])
    state_1 = opp.states.get(f"device_tracker.{device_name}")
    assert state_1.state == STATE_HOME

    assert len(opp.data[DOMAIN]["devices"]) == 1
    entry = opp.config_entries.async_entries(DOMAIN)[0]

    assert await opp.config_entries.async_unload(entry.entry_id)
    await opp.async_block_till_done()
    assert len(opp.data[DOMAIN]["devices"]) == 0

    assert await opp.config_entries.async_setup(entry.entry_id)
    await opp.async_block_till_done()

    state_2 = opp.states.get(f"device_tracker.{device_name}")
    assert state_2 is not None
    assert state_1 is not state_2

    assert state_2.state == STATE_HOME
    assert state_2.attributes[ATTR_LATITUDE] == HOME_LATITUDE
    assert state_2.attributes[ATTR_LONGITUDE] == HOME_LONGITUDE
Example #6
0
    async def async_step_user(self, user_input=None):
        """Step when user initializes a integration."""
        self._errors = {}
        if user_input is not None:
            name = slugify(user_input[CONF_NAME])
            prt = user_input[CONF_PORT]
            if not self._prt_in_configuration_exists(prt):
                if self._test_connection(prt):
                    return self._create_device(name, prt)
            else:
                self._errors[CONF_PORT] = "already_configured"
        else:
            user_input = {}
            user_input[CONF_NAME] = ""
            user_input[CONF_PORT] = ""

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {
                    vol.Required(CONF_NAME, default=user_input[CONF_NAME]): str,
                    vol.Required(CONF_PORT, default=user_input[CONF_PORT]): str,
                }
            ),
            errors=self._errors,
        )
Example #7
0
async def validate_input(data):
    """Validate the user input allows us to connect.

    Data has the keys from DATA_SCHEMA with values provided by the user.
    """
    userid = data.get(CONF_USERNAME)
    password = data.get(CONF_PASSWORD)

    prefix = data[CONF_PREFIX]
    url = _make_url_from_data(data)
    requires_password = url.startswith("elks://")

    if requires_password and (not userid or not password):
        raise InvalidAuth

    elk = elkm1.Elk(
        {"url": url, "userid": userid, "password": password, "element_list": ["panel"]}
    )
    elk.connect()

    if not await async_wait_for_elk_to_sync(elk, VALIDATE_TIMEOUT, url):
        raise InvalidAuth

    device_name = data[CONF_PREFIX] if data[CONF_PREFIX] else "ElkM1"
    # Return info that you want to store in the config entry.
    return {"title": device_name, CONF_HOST: url, CONF_PREFIX: slugify(prefix)}
Example #8
0
def _parse_see_args(message, subscribe_topic):
    """Parse the OwnTracks location parameters, into the format see expects.

    Async friendly.
    """
    user, device = _parse_topic(message["topic"], subscribe_topic)
    dev_id = slugify(f"{user}_{device}")
    kwargs = {"dev_id": dev_id, "host_name": user, "attributes": {}}
    if message["lat"] is not None and message["lon"] is not None:
        kwargs["gps"] = (message["lat"], message["lon"])
    else:
        kwargs["gps"] = None

    if "acc" in message:
        kwargs["gps_accuracy"] = message["acc"]
    if "batt" in message:
        kwargs["battery"] = message["batt"]
    if "vel" in message:
        kwargs["attributes"]["velocity"] = message["vel"]
    if "tid" in message:
        kwargs["attributes"]["tid"] = message["tid"]
    if "addr" in message:
        kwargs["attributes"]["address"] = message["addr"]
    if "cog" in message:
        kwargs["attributes"]["course"] = message["cog"]
    if "bs" in message:
        kwargs["attributes"]["battery_status"] = message["bs"]
    if "t" in message:
        if message["t"] in ("c", "u"):
            kwargs["source_type"] = SOURCE_TYPE_GPS
        if message["t"] == "b":
            kwargs["source_type"] = SOURCE_TYPE_BLUETOOTH_LE

    return dev_id, kwargs
Example #9
0
async def async_handle_waypoint(opp, name_base, waypoint):
    """Handle a waypoint."""
    name = waypoint["desc"]
    pretty_name = f"{name_base} - {name}"
    lat = waypoint["lat"]
    lon = waypoint["lon"]
    rad = waypoint["rad"]

    # check zone exists
    entity_id = zone_comp.ENTITY_ID_FORMAT.format(slugify(pretty_name))

    # Check if state already exists
    if opp.states.get(entity_id) is not None:
        return

    zone = zone_comp.Zone.from_yaml(
        {
            zone_comp.CONF_NAME: pretty_name,
            zone_comp.CONF_LATITUDE: lat,
            zone_comp.CONF_LONGITUDE: lon,
            zone_comp.CONF_RADIUS: rad,
            zone_comp.CONF_ICON: zone_comp.ICON_IMPORT,
            zone_comp.CONF_PASSIVE: False,
        }, )
    zone.opp = opp
    zone.entity_id = entity_id
    zone.async_write_op_state()
Example #10
0
 def __init__(self, tesla_device, coordinator):
     """Initialise the Tesla device."""
     super().__init__(coordinator)
     self.tesla_device = tesla_device
     self._name = self.tesla_device.name
     self._unique_id = slugify(self.tesla_device.uniq_name)
     self._attributes = self.tesla_device.attrs.copy()
Example #11
0
    def _update_info(self, now=None) -> None:
        """Update the device info."""
        _LOGGER.debug("Updating devices %s", now)

        # Update self.devices to collect new devices added
        # to the users account.
        self.devices = self.api.get_trackrs()

        for trackr in self.devices:
            trackr.update_state()
            trackr_id = trackr.tracker_id()
            trackr_device_id = trackr.id()
            lost = trackr.lost()
            dev_id = slugify(trackr.name())
            if dev_id is None:
                dev_id = trackr_id
            location = trackr.last_known_location()
            lat = location["latitude"]
            lon = location["longitude"]

            attrs = {
                "last_updated": trackr.last_updated(),
                "last_seen": trackr.last_time_seen(),
                "trackr_id": trackr_id,
                "id": trackr_device_id,
                "lost": lost,
                "battery_level": trackr.battery_level(),
            }

            self.see(dev_id=dev_id, gps=(lat, lon), attributes=attrs)
Example #12
0
    def play_sound(service: ServiceDataType) -> None:
        """Play sound on the device."""
        account = service.data[ATTR_ACCOUNT]
        device_name = service.data.get(ATTR_DEVICE_NAME)
        device_name = slugify(device_name.replace(" ", "", 99))

        for device in _get_account(account).get_devices_with_name(device_name):
            device.play_sound()
Example #13
0
 def __init__(self, opp, addr, name):
     """Register callback that will be used for signals."""
     self._opp = opp
     self._addr = addr
     self._name = name
     self._id = slugify(self._name)
     signal = f"homeworks_entity_{self._addr}"
     async_dispatcher_connect(self._opp, signal, self._update_callback)
Example #14
0
 def attrs(self):
     """Return device attributes."""
     attr_data = self._wireless_params if self._wireless_params else self._params
     for attr in ATTR_DEVICE_TRACKER:
         if attr in attr_data:
             self._attrs[slugify(attr)] = attr_data[attr]
     self._attrs["ip_address"] = self._params.get("active-address")
     return self._attrs
Example #15
0
def _parse_update_data(topic, data):
    """Parse the room presence update."""
    parts = topic.split("/")
    room = parts[-1]
    device_id = slugify(data.get(ATTR_ID)).upper()
    distance = data.get("distance")
    parsed_data = {ATTR_DEVICE_ID: device_id, ATTR_ROOM: room, ATTR_DISTANCE: distance}
    return parsed_data
Example #16
0
def _name_validator(config):
    """Validate the name."""
    config = copy.deepcopy(config)
    for address, device_config in config[CONF_DEVICES].items():
        if CONF_NAME not in device_config:
            device_config[CONF_NAME] = util.slugify(address)

    return config
Example #17
0
    def __init__(self, device, gateway):
        """Register callback that will be used for signals."""
        super().__init__(device, gateway)

        self._device.register_callback(self.async_update_callback)

        self.device_id = None
        self.event_id = slugify(self._device.name)
        LOGGER.debug("deCONZ event created: %s", self.event_id)
Example #18
0
    def display_message(service: ServiceDataType) -> None:
        """Display a message on the device."""
        account = service.data[ATTR_ACCOUNT]
        device_name = service.data.get(ATTR_DEVICE_NAME)
        device_name = slugify(device_name.replace(" ", "", 99))
        message = service.data.get(ATTR_LOST_DEVICE_MESSAGE)
        sound = service.data.get(ATTR_LOST_DEVICE_SOUND, False)

        for device in _get_account(account).get_devices_with_name(device_name):
            device.display_message(message, sound)
Example #19
0
 def append_keys(self, resource: dict, prefix: str | None = None) -> None:
     """Properly format key val pairs to append to attributes."""
     for attr, val in resource.items():
         if val == "" or val is None or attr == "feed_id":
             continue
         key = attr
         if prefix and not key.startswith(prefix):
             key = f"{prefix} {key}"
         key = slugify(key)
         self._attributes[key] = val
Example #20
0
    def lost_device(service: ServiceDataType) -> None:
        """Make the device in lost state."""
        account = service.data[ATTR_ACCOUNT]
        device_name = service.data.get(ATTR_DEVICE_NAME)
        device_name = slugify(device_name.replace(" ", "", 99))
        number = service.data.get(ATTR_LOST_DEVICE_NUMBER)
        message = service.data.get(ATTR_LOST_DEVICE_MESSAGE)

        for device in _get_account(account).get_devices_with_name(device_name):
            device.lost_device(number, message)
Example #21
0
def _component_to_unique_id(server_id: str, component: str,
                            instance_num: int) -> str:
    """Convert a component to a unique_id."""
    return get_hyperion_unique_id(
        server_id,
        instance_num,
        slugify(
            f"{TYPE_HYPERION_COMPONENT_SWITCH_BASE} {KEY_COMPONENTID_TO_NAME[component]}"
        ),
    )
Example #22
0
    def __init__(self, vera_scene: veraApi.VeraScene,
                 controller_data: ControllerData) -> None:
        """Initialize the scene."""
        self.vera_scene = vera_scene
        self.controller = controller_data.controller

        self._name = self.vera_scene.name
        # Append device id to prevent name clashes in HA.
        self.vera_id = VERA_ID_FORMAT.format(slugify(vera_scene.name),
                                             vera_scene.scene_id)
Example #23
0
async def test_beacon_enter_and_exit_home(opp, geofency_client, webhook_id):
    """Test iBeacon based zone enter and exit - a.k.a stationary iBeacon."""
    url = f"/api/webhook/{webhook_id}"

    # Enter the Home zone
    req = await geofency_client.post(url, data=BEACON_ENTER_HOME)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(f"beacon_{BEACON_ENTER_HOME['name']}")
    state_name = opp.states.get(f"device_tracker.{device_name}").state
    assert state_name == STATE_HOME

    # Exit the Home zone
    req = await geofency_client.post(url, data=BEACON_EXIT_HOME)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(f"beacon_{BEACON_ENTER_HOME['name']}")
    state_name = opp.states.get(f"device_tracker.{device_name}").state
    assert state_name == STATE_NOT_HOME
Example #24
0
async def async_setup(opp, opp_config):
    """Set up the Geofency component."""
    config = opp_config.get(DOMAIN, {})
    mobile_beacons = config.get(CONF_MOBILE_BEACONS, [])
    opp.data[DOMAIN] = {
        "beacons": [slugify(beacon) for beacon in mobile_beacons],
        "devices": set(),
        "unsub_device_tracker": {},
    }
    return True
Example #25
0
    def generate_id(self, suggestion: str) -> str:
        """Generate an ID."""
        base = slugify(suggestion)
        proposal = base
        attempt = 1

        while self.has_id(proposal):
            attempt += 1
            proposal = f"{base}_{attempt}"

        return proposal
Example #26
0
    async def async_register_services(self) -> None:
        """Create or update the notify services."""
        if hasattr(self, "targets"):
            stale_targets = set(self.registered_targets)

            # pylint: disable=no-member
            for name, target in self.targets.items():  # type: ignore
                target_name = slugify(f"{self._target_service_name_prefix}_{name}")
                if target_name in stale_targets:
                    stale_targets.remove(target_name)
                if (
                    target_name in self.registered_targets
                    and target == self.registered_targets[target_name]
                ):
                    continue
                self.registered_targets[target_name] = target
                self.opp.services.async_register(
                    DOMAIN,
                    target_name,
                    self._async_notify_message_service,
                    schema=NOTIFY_SERVICE_SCHEMA,
                )
                # Register the service description
                service_desc = {
                    CONF_NAME: f"Send a notification via {target_name}",
                    CONF_DESCRIPTION: f"Sends a notification message using the {target_name} integration.",
                    CONF_FIELDS: self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
                }
                async_set_service_schema(self.opp, DOMAIN, target_name, service_desc)

            for stale_target_name in stale_targets:
                del self.registered_targets[stale_target_name]
                self.opp.services.async_remove(
                    DOMAIN,
                    stale_target_name,
                )

        if self.opp.services.has_service(DOMAIN, self._service_name):
            return

        self.opp.services.async_register(
            DOMAIN,
            self._service_name,
            self._async_notify_message_service,
            schema=NOTIFY_SERVICE_SCHEMA,
        )

        # Register the service description
        service_desc = {
            CONF_NAME: f"Send a notification with {self._service_name}",
            CONF_DESCRIPTION: f"Sends a notification message using the {self._service_name} service.",
            CONF_FIELDS: self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
        }
        async_set_service_schema(self.opp, DOMAIN, self._service_name, service_desc)
Example #27
0
def url_slug(value: Any) -> str:
    """Validate value is a valid url slug."""
    if value is None:
        raise vol.Invalid("Slug should not be None")
    if "-" not in value:
        raise vol.Invalid("Url path needs to contain a hyphen (-)")
    str_value = str(value)
    slg = slugify(str_value, separator="-")
    if str_value == slg:
        return str_value
    raise vol.Invalid(f"invalid slug {value} (try {slg})")
Example #28
0
 def __init__(self, name, state_topic, device_id, timeout, consider_home):
     """Initialize the sensor."""
     self._state = STATE_NOT_HOME
     self._name = name
     self._state_topic = "{}{}".format(state_topic, "/+")
     self._device_id = slugify(device_id).upper()
     self._timeout = timeout
     self._consider_home = (timedelta(
         seconds=consider_home) if consider_home else None)
     self._distance = None
     self._updated = None
Example #29
0
async def test_gps_enter_and_exit_home(opp, geofency_client, webhook_id):
    """Test GPS based zone enter and exit."""
    url = f"/api/webhook/{webhook_id}"

    # Enter the Home zone
    req = await geofency_client.post(url, data=GPS_ENTER_HOME)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(GPS_ENTER_HOME["device"])
    state_name = opp.states.get(f"device_tracker.{device_name}").state
    assert state_name == STATE_HOME

    # Exit the Home zone
    req = await geofency_client.post(url, data=GPS_EXIT_HOME)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(GPS_EXIT_HOME["device"])
    state_name = opp.states.get(f"device_tracker.{device_name}").state
    assert state_name == STATE_NOT_HOME

    # Exit the Home zone with "Send Current Position" enabled
    data = GPS_EXIT_HOME.copy()
    data["currentLatitude"] = NOT_HOME_LATITUDE
    data["currentLongitude"] = NOT_HOME_LONGITUDE

    req = await geofency_client.post(url, data=data)
    await opp.async_block_till_done()
    assert req.status == HTTP_OK
    device_name = slugify(GPS_EXIT_HOME["device"])
    current_latitude = opp.states.get(
        f"device_tracker.{device_name}").attributes["latitude"]
    assert current_latitude == NOT_HOME_LATITUDE
    current_longitude = opp.states.get(
        f"device_tracker.{device_name}").attributes["longitude"]
    assert current_longitude == NOT_HOME_LONGITUDE

    dev_reg = dr.async_get(opp)
    assert len(dev_reg.devices) == 1

    ent_reg = er.async_get(opp)
    assert len(ent_reg.entities) == 1
Example #30
0
    async def import_device_data(self):
        """Import device data from Traccar."""
        for device_unique_id in self._api.device_info:
            device_info = self._api.device_info[device_unique_id]
            device = None
            attr = {}
            skip_accuracy_filter = False

            attr[ATTR_TRACKER] = "traccar"
            if device_info.get("address") is not None:
                attr[ATTR_ADDRESS] = device_info["address"]
            if device_info.get("geofence") is not None:
                attr[ATTR_GEOFENCE] = device_info["geofence"]
            if device_info.get("category") is not None:
                attr[ATTR_CATEGORY] = device_info["category"]
            if device_info.get("speed") is not None:
                attr[ATTR_SPEED] = device_info["speed"]
            if device_info.get("motion") is not None:
                attr[ATTR_MOTION] = device_info["motion"]
            if device_info.get("traccar_id") is not None:
                attr[ATTR_TRACCAR_ID] = device_info["traccar_id"]
                for dev in self._api.devices:
                    if dev["id"] == device_info["traccar_id"]:
                        device = dev
                        break
            if device is not None and device.get("status") is not None:
                attr[ATTR_STATUS] = device["status"]
            for custom_attr in self._custom_attributes:
                if device_info.get(custom_attr) is not None:
                    attr[custom_attr] = device_info[custom_attr]
                    if custom_attr in self._skip_accuracy_on:
                        skip_accuracy_filter = True

            accuracy = 0.0
            if device_info.get("accuracy") is not None:
                accuracy = device_info["accuracy"]
            if (not skip_accuracy_filter and self._max_accuracy > 0
                    and accuracy > self._max_accuracy):
                _LOGGER.debug(
                    "Excluded position by accuracy filter: %f (%s)",
                    accuracy,
                    attr[ATTR_TRACCAR_ID],
                )
                continue

            await self._async_see(
                dev_id=slugify(device_info["device_id"]),
                gps=(device_info.get("latitude"),
                     device_info.get("longitude")),
                gps_accuracy=accuracy,
                battery=device_info.get("battery"),
                attributes=attr,
            )