Skip to content

Commit

Permalink
🗑️ v2.5.4 clean up; add integration_type (#123)
Browse files Browse the repository at this point in the history
Signed-off-by: Ludy87 <Ludy87@users.noreply.github.com>

Signed-off-by: Ludy87 <Ludy87@users.noreply.github.com>
  • Loading branch information
Ludy87 authored Dec 3, 2022
1 parent d59be13 commit 6e45c46
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 246 deletions.
6 changes: 3 additions & 3 deletions custom_components/xplora_watch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

from .const import DATA_HASS_CONFIG, DOMAIN
from .coordinator import XploraDataUpdateCoordinator
from .helper import set_service_yaml
from .helper import create_service_yaml_file
from .services import async_setup_services, async_unload_services

PLATFORMS = [Platform.DEVICE_TRACKER, Platform.BINARY_SENSOR, Platform.NOTIFY, Platform.SENSOR, Platform.SWITCH]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.DEVICE_TRACKER, Platform.NOTIFY, Platform.SENSOR, Platform.SWITCH]

_LOGGER = logging.getLogger(__name__)

Expand All @@ -41,7 +41,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN][entry.entry_id] = coordinator
watches = await coordinator.controller.setDevices()

set_service_yaml(hass, entry, watches)
create_service_yaml_file(hass, entry, watches)

for platform in PLATFORMS:
if platform != Platform.NOTIFY:
Expand Down
70 changes: 40 additions & 30 deletions custom_components/xplora_watch/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ID, ATTR_LATITUDE, ATTR_LONGITUDE, CONF_NAME, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import (
Expand All @@ -28,14 +29,26 @@
)
from .coordinator import XploraDataUpdateCoordinator
from .entity import XploraBaseEntity
from .helper import get_location_distance
from .helper import is_distance_in_radius

_LOGGER = logging.getLogger(__name__)

BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
BinarySensorEntityDescription(key=BINARY_SENSOR_CHARGING, device_class=BinarySensorDeviceClass.BATTERY_CHARGING),
BinarySensorEntityDescription(key=BINARY_SENSOR_SAFEZONE, device_class=BinarySensorDeviceClass.SAFETY),
BinarySensorEntityDescription(key=BINARY_SENSOR_STATE, device_class=BinarySensorDeviceClass.CONNECTIVITY),
BinarySensorEntityDescription(
key=BINARY_SENSOR_CHARGING,
device_class=BinarySensorDeviceClass.BATTERY_CHARGING,
entity_category=EntityCategory.DIAGNOSTIC,
),
BinarySensorEntityDescription(
key=BINARY_SENSOR_SAFEZONE,
device_class=BinarySensorDeviceClass.SAFETY,
entity_category=EntityCategory.DIAGNOSTIC,
),
BinarySensorEntityDescription(
key=BINARY_SENSOR_STATE,
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_category=EntityCategory.DIAGNOSTIC,
),
)


Expand All @@ -62,9 +75,6 @@ async def async_setup_entry(


class XploraBinarySensor(XploraBaseEntity, BinarySensorEntity):

_attr_force_update = False

def __init__(
self,
config_entry: ConfigEntry,
Expand All @@ -75,52 +85,52 @@ def __init__(
description: BinarySensorEntityDescription,
) -> None:
super().__init__(config_entry, description, coordinator, ward, sw_version, wuid)
_wuid: str = ""
for i in range(1, len(config_entry.options.get(CONF_WATCHES, [])) + 1):
_wuid = config_entry.options.get(f"{CONF_WATCHES}_{i}", "")
if _wuid.find("=") != -1:
friendly_name = _wuid.split("=")
if friendly_name[0] == wuid:
self._attr_name: str = f"{friendly_name[1]} {description.key}".title()
else:
self._attr_name: str = f"{ward.get(CONF_NAME)} {ATTR_WATCH} {description.key} {wuid}".title()
i = (self._options.get(CONF_WATCHES, []).index(wuid) + 1) if self._options.get(CONF_WATCHES, []) else -1
if i == -1:
return
_wuid: str = self._options.get(f"{CONF_WATCHES}_{i}", "")
if _wuid.find("=") != -1:
friendly_name = _wuid.split("=")
if friendly_name[0] == wuid:
self._attr_name: str = f'{friendly_name[1]} {description.key.replace("_", " ")}'.title()
else:
self._attr_name: str = f"{ward.get(CONF_NAME)} {ATTR_WATCH} {description.key} {wuid}".title()
self._attr_name: str = f'{ward.get(CONF_NAME)} {ATTR_WATCH} {description.key.replace("_", " ")} {wuid}'.title()
else:
self._attr_name: str = f'{ward.get(CONF_NAME)} {ATTR_WATCH} {description.key.replace("_", " ")} {wuid}'.title()

self._attr_unique_id = f"{ward.get(CONF_NAME)}-{ATTR_WATCH}-{description.key}-{wuid}"
self._config_entry = config_entry
_LOGGER.debug(
"Updating binary_sensor: %s | %s | Watch_ID %s",
"Updating binary_sensor: %s | %s | %s Watch_ID %s",
self._attr_name[:-33] if _wuid.find("=") == -1 else self._attr_name,
description.key,
i,
wuid[25:],
)

@property
def is_on(self) -> bool:
"""Return true if the binary sensor is on."""
if self.entity_description.key == BINARY_SENSOR_CHARGING:
return self._coordinator.data[self.watch_uid]["isCharging"]
return self.coordinator.data[self.watch_uid]["isCharging"]
if self.entity_description.key == BINARY_SENSOR_STATE:
return self._coordinator.data[self.watch_uid]["isOnline"]
return self.coordinator.data[self.watch_uid]["isOnline"]
if self.entity_description.key == BINARY_SENSOR_SAFEZONE:
_options = self._config_entry.options
if _options.get(CONF_HOME_SAFEZONE, STATE_OFF) == STATE_ON:
latitude = self._coordinator.data[self.watch_uid][ATTR_TRACKER_LAT]
longitude = self._coordinator.data[self.watch_uid][ATTR_TRACKER_LNG]
if self._options.get(CONF_HOME_SAFEZONE, STATE_OFF) == STATE_ON:
latitude = self.coordinator.data[self.watch_uid][ATTR_TRACKER_LAT]
longitude = self.coordinator.data[self.watch_uid][ATTR_TRACKER_LNG]
home_latitude = self.hass.states.get(HOME).attributes[ATTR_LATITUDE]
home_longitude = self.hass.states.get(HOME).attributes[ATTR_LONGITUDE]
home_raduis = self.hass.states.get(HOME).attributes["radius"]
if get_location_distance(
if is_distance_in_radius(
(
_options.get(CONF_HOME_LATITUDE, home_latitude),
_options.get(CONF_HOME_LONGITUDE, home_longitude),
self._options.get(CONF_HOME_LATITUDE, home_latitude),
self._options.get(CONF_HOME_LONGITUDE, home_longitude),
),
(latitude, longitude),
_options.get(CONF_HOME_RADIUS, home_raduis),
self._options.get(CONF_HOME_RADIUS, home_raduis),
):
return False
return self._coordinator.data[self.watch_uid]["isSafezone"]
return self.coordinator.data[self.watch_uid]["isSafezone"]
return False

@property
Expand Down
17 changes: 10 additions & 7 deletions custom_components/xplora_watch/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ async def validate_input(hass: core.HomeAssistant, data: dict[str, Any]) -> dict
)

try:
await account.init(True)
await account.init()
except LoginError as err:
raise LoginError(err.message)

Expand Down Expand Up @@ -166,13 +166,13 @@ async def async_step_user_phone(self, user_input: dict[str, Any] | None = None)
try:
info = await validate_input(self.hass, user_input)
except PhoneOrEmailFail as e:
_LOGGER.error(e)
_LOGGER.exception(e)
errors["base"] = "phone_email_invalid"
except LoginError as e:
_LOGGER.error(e)
_LOGGER.exception(e)
errors["base"] = "pass_invalid"
except Exception as e:
_LOGGER.error(e)
_LOGGER.exception(e)
errors["base"] = "cannot_connect"

if info:
Expand All @@ -196,10 +196,13 @@ async def async_step_user_email(self, user_input: dict[str, Any] | None = None)
try:
info = await validate_input(self.hass, user_input)
except PhoneOrEmailFail as e:
_LOGGER.error(e)
_LOGGER.exception(e)
errors["base"] = "phone_email_invalid"
except LoginError as e:
_LOGGER.error(e)
_LOGGER.exception(e)
errors["base"] = "pass_invalid"
except Exception as e:
_LOGGER.exception(e)
errors["base"] = "cannot_connect"

if info:
Expand Down Expand Up @@ -229,7 +232,7 @@ async def async_step_init(self, user_input: dict[str, Any] | None = None) -> Flo
self.config_entry.data.get(CONF_TIMEZONE, None),
email=self.config_entry.data.get(CONF_EMAIL, None),
)
await controller.init(True)
await controller.init()
watches = await controller.setDevices()
_options = self.config_entry.options

Expand Down
5 changes: 4 additions & 1 deletion custom_components/xplora_watch/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
DEVICE_NAME: Final = "Xplora® Watch"
ATTRIBUTION: Final = "Data provided by Xplora®"

URL_OPENSTREETMAP = "https://nominatim.openstreetmap.org/reverse?lat={}&lon={}&format=jsonv2"
URL_OPENSTREETMAP = "https://nominatim.openstreetmap.org/reverse?lat={}&lon={}&format=jsonv2&accept-language={}"

ATTR_SERVICE_MSG: Final = "message"
ATTR_SERVICE_SEE: Final = "see"
Expand Down Expand Up @@ -48,6 +48,7 @@
CONF_WATCHES: Final = "watches"

SENSOR_BATTERY: Final = "battery"
SENSOR_DISTANCE: Final = "distance"
SENSOR_MESSAGE: Final = "message"
SENSOR_STEP_DAY: Final = "step_day"
SENSOR_XCOIN: Final = "xcoin"
Expand Down Expand Up @@ -114,6 +115,7 @@
DEVICE_TRACKER_SAFZONES: "show Safezone",
DEVICE_TRACKER_WATCH: "Watch tracking",
SENSOR_BATTERY: "Battery state",
SENSOR_DISTANCE: "Distance",
SENSOR_MESSAGE: "Read Message(s) from Account",
SENSOR_STEP_DAY: "Steps per Day",
SENSOR_XCOIN: "XCoins",
Expand All @@ -127,6 +129,7 @@
DEVICE_TRACKER_SAFZONES: "Sicherheitszone(n) anzeigen",
DEVICE_TRACKER_WATCH: "Watch Tracking",
SENSOR_BATTERY: "Batterie-Status",
SENSOR_DISTANCE: "Distanz",
SENSOR_MESSAGE: "Nachricht(en) vom Account",
SENSOR_STEP_DAY: "Schritte pro Tag",
SENSOR_XCOIN: "XCoins",
Expand Down
21 changes: 13 additions & 8 deletions custom_components/xplora_watch/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import aiohttp
from pyxplora_api import pyxplora_api_async as PXA

from homeassistant.components.device_tracker.const import ATTR_BATTERY, ATTR_LOCATION_NAME
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, CONF_SCAN_INTERVAL
from homeassistant.core import HomeAssistant
Expand All @@ -22,13 +23,15 @@
ATTR_TRACKER_POI,
ATTR_TRACKER_RAD,
CONF_COUNTRY_CODE,
CONF_LANGUAGE,
CONF_MAPS,
CONF_MESSAGE,
CONF_OPENCAGE_APIKEY,
CONF_PHONENUMBER,
CONF_TIMEZONE,
CONF_USERLANG,
CONF_WATCHES,
DEFAULT_LANGUAGE,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
MAPS,
Expand Down Expand Up @@ -63,7 +66,7 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
)

async def init(self) -> None:
await self.controller.init(True)
await self.controller.init()

async def _async_update_watch_data(self, targets: list[str] | None = None) -> dict[str, Any]:
"""Fetch data from Xplora®."""
Expand All @@ -85,7 +88,7 @@ async def _async_update_watch_data(self, targets: list[str] | None = None) -> di
).get("chatsNew", {"list: []"})

watchLocate: dict[str, Any] = device.get("loadWatchLocation", {})

self.unreadMsg = await self.controller.getWatchUnReadChatMsgCount(wuid)
self.battery = watchLocate.get("watch_battery", -1)
self.isCharging = watchLocate.get("watch_charging", False)
self.lat = float(watchLocate.get(ATTR_TRACKER_LAT, 0.0))
Expand Down Expand Up @@ -116,7 +119,6 @@ async def _async_update_watch_data(self, targets: list[str] | None = None) -> di

self._step_day = device.get("getWatchUserSteps", {}).get("day")
self._xcoin = device.get("getWatchUserXcoins", Any)
timeout = aiohttp.ClientTimeout(total=2)
licence = None
if self.maps == MAPS[1]:
async with OpenCageGeocodeUA(self.opencage_apikey) as geocoder:
Expand All @@ -126,19 +128,22 @@ async def _async_update_watch_data(self, targets: list[str] | None = None) -> di
self.location_name = "{}".format(results[0]["formatted"])
_LOGGER.debug("load address from opencagedata.com")
else:
language = self._entry.options.get(CONF_LANGUAGE, self._entry.data.get(CONF_LANGUAGE, DEFAULT_LANGUAGE))
timeout = aiohttp.ClientTimeout(total=2)
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(URL_OPENSTREETMAP.format(self.lat, self.lng)) as response:
async with session.get(URL_OPENSTREETMAP.format(self.lat, self.lng, language)) as response:
await session.close()
res: dict[str, Any] = await response.json()
licence = res.get(ATTR_TRACKER_LICENCE, None)
address: dict[str, str] = res.get(ATTR_TRACKER_ADDR, [])
address: dict[str, str] = res.get(ATTR_TRACKER_ADDR, {})
if address:
self.location_name = "{}".format(res.get("display_name", ""))
_LOGGER.debug("load address from openstreetmap.org")
self.watch_entry.update(
{
wuid: {
"battery": self.battery if self.battery != -1 else None,
"unreadMsg": self.unreadMsg,
ATTR_BATTERY: self.battery if self.battery != -1 else None,
"isCharging": self.isCharging if self.battery != -1 else None,
"isOnline": self.isOnline,
"isSafezone": self.isSafezone,
Expand All @@ -148,8 +153,8 @@ async def _async_update_watch_data(self, targets: list[str] | None = None) -> di
"xcoin": self._xcoin,
ATTR_TRACKER_LAT: self.lat if self.isOnline else None,
ATTR_TRACKER_LNG: self.lng if self.isOnline else None,
ATTR_TRACKER_POI: self.poi,
"location_name": self.location_name,
ATTR_TRACKER_POI: self.poi if self.poi else None,
ATTR_LOCATION_NAME: self.location_name,
ATTR_TRACKER_IMEI: self.imei,
"location_accuracy": self.location_accuracy,
"entity_picture": self.entity_picture,
Expand Down
Loading

0 comments on commit 6e45c46

Please sign in to comment.