mirror of
https://github.com/cyberjunky/home-assistant-garmin_connect.git
synced 2026-01-09 12:57:58 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17fa2bcc63 | ||
|
|
b26f36c41f | ||
|
|
845cce3bda | ||
|
|
15800b00d5 | ||
|
|
c9e9740137 | ||
|
|
b7f2a6e653 | ||
|
|
be150124b7 | ||
|
|
28876a8709 | ||
|
|
287a9a04c3 | ||
|
|
de51403c43 | ||
|
|
36e5b7c6b8 | ||
|
|
9a6aea06c4 | ||
|
|
bc1ff88af2 | ||
|
|
48d738d1dc | ||
|
|
d57b8e0223 | ||
|
|
0688f89be1 | ||
|
|
985468d7a2 | ||
|
|
ff0ccb7e99 | ||
|
|
f59b41e7c4 | ||
|
|
0074b94723 | ||
|
|
ee777314f9 | ||
|
|
58f5dd49db | ||
|
|
7b66c4b7be | ||
|
|
1aa8cfb78f | ||
|
|
a29be3127e | ||
|
|
ef91580157 | ||
|
|
1c3e5a4385 | ||
|
|
b6aebe1637 | ||
|
|
fa48f9f4e2 | ||
|
|
4f4d0b8425 | ||
|
|
8760bc0a78 | ||
|
|
8efd365163 | ||
|
|
cc6e0af4e5 |
15
.github/workflows/hassfest.yml
vendored
15
.github/workflows/hassfest.yml
vendored
@@ -1,15 +0,0 @@
|
||||
|
||||
name: Validate with hassfest
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: "actions/checkout@v2"
|
||||
- uses: home-assistant/actions/hassfest@master
|
||||
@@ -1,6 +1,9 @@
|
||||
"""The Garmin Connect integration."""
|
||||
from datetime import date
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import asyncio
|
||||
from collections.abc import Awaitable
|
||||
|
||||
from garminconnect import (
|
||||
Garmin,
|
||||
@@ -12,10 +15,16 @@ from garminconnect import (
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.exceptions import ConfigEntryNotReady, IntegrationError
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import DATA_COORDINATOR, DEFAULT_UPDATE_INTERVAL, DOMAIN
|
||||
from .const import (
|
||||
DATA_COORDINATOR,
|
||||
DEFAULT_UPDATE_INTERVAL,
|
||||
DOMAIN,
|
||||
GEAR,
|
||||
SERVICE_SETTING,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,11 +42,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
DATA_COORDINATOR: coordinator,
|
||||
}
|
||||
hass.data[DOMAIN][entry.entry_id] = {DATA_COORDINATOR: coordinator}
|
||||
|
||||
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
||||
@@ -57,8 +64,13 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
"""Initialize the Garmin Connect hub."""
|
||||
self.entry = entry
|
||||
self.hass = hass
|
||||
self.in_china = False
|
||||
|
||||
self._api = Garmin(entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD])
|
||||
country = self.hass.config.country
|
||||
if country == "CN":
|
||||
self.in_china = True
|
||||
|
||||
self._api = Garmin(entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], self.in_china)
|
||||
|
||||
super().__init__(
|
||||
hass, _LOGGER, name=DOMAIN, update_interval=DEFAULT_UPDATE_INTERVAL
|
||||
@@ -97,9 +109,31 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
body = await self.hass.async_add_executor_job(
|
||||
self._api.get_body_composition, date.today().isoformat()
|
||||
)
|
||||
activities = await self.hass.async_add_executor_job(
|
||||
self._api.get_activities_by_date, (date.today()-timedelta(days=7)).isoformat(), (date.today()+timedelta(days=1)).isoformat()
|
||||
)
|
||||
|
||||
|
||||
_LOGGER.debug(body)
|
||||
alarms = await self.hass.async_add_executor_job(self._api.get_device_alarms)
|
||||
_LOGGER.debug(alarms)
|
||||
gear = await self.hass.async_add_executor_job(
|
||||
self._api.get_gear, summary[GEAR.USERPROFILE_ID]
|
||||
)
|
||||
tasks: list[Awaitable] = [
|
||||
self.hass.async_add_executor_job(
|
||||
self._api.get_gear_stats, gear_item[GEAR.UUID]
|
||||
)
|
||||
for gear_item in gear
|
||||
]
|
||||
gear_stats = await asyncio.gather(*tasks)
|
||||
activity_types = await self.hass.async_add_executor_job(
|
||||
self._api.get_activity_types
|
||||
)
|
||||
gear_defaults = await self.hass.async_add_executor_job(
|
||||
self._api.get_gear_defaults, summary[GEAR.USERPROFILE_ID]
|
||||
)
|
||||
|
||||
except (
|
||||
GarminConnectAuthenticationError,
|
||||
GarminConnectTooManyRequestsError,
|
||||
@@ -110,8 +144,58 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
raise UpdateFailed(error) from error
|
||||
return {}
|
||||
|
||||
summary['lastActivities'] = activities
|
||||
|
||||
return {
|
||||
**summary,
|
||||
**body["totalAverage"],
|
||||
"nextAlarm": alarms,
|
||||
"gear": gear,
|
||||
"gear_stats": gear_stats,
|
||||
"activity_types": activity_types,
|
||||
"gear_defaults": gear_defaults,
|
||||
}
|
||||
|
||||
async def set_active_gear(self, entity, service_data):
|
||||
"""Update Garmin Gear settings"""
|
||||
if not await self.async_login():
|
||||
raise IntegrationError(
|
||||
"Failed to login to Garmin Connect, unable to update"
|
||||
)
|
||||
|
||||
setting = service_data.data["setting"]
|
||||
activity_type_id = next(
|
||||
filter(
|
||||
lambda a: a[GEAR.TYPE_KEY] == service_data.data["activity_type"],
|
||||
self.data["activity_types"],
|
||||
)
|
||||
)[GEAR.TYPE_ID]
|
||||
if setting != SERVICE_SETTING.ONLY_THIS_AS_DEFAULT:
|
||||
await self.hass.async_add_executor_job(
|
||||
self._api.set_gear_default,
|
||||
activity_type_id,
|
||||
entity.uuid,
|
||||
setting == SERVICE_SETTING.DEFAULT,
|
||||
)
|
||||
else:
|
||||
old_default_state = await self.hass.async_add_executor_job(
|
||||
self._api.get_gear_defaults, self.data[GEAR.USERPROFILE_ID]
|
||||
)
|
||||
to_deactivate = list(
|
||||
filter(
|
||||
lambda o: o[GEAR.ACTIVITY_TYPE_PK] == activity_type_id
|
||||
and o[GEAR.UUID] != entity.uuid,
|
||||
old_default_state,
|
||||
)
|
||||
)
|
||||
|
||||
for active_gear in to_deactivate:
|
||||
await self.hass.async_add_executor_job(
|
||||
self._api.set_gear_default,
|
||||
activity_type_id,
|
||||
active_gear[GEAR.UUID],
|
||||
False,
|
||||
)
|
||||
await self.hass.async_add_executor_job(
|
||||
self._api.set_gear_default, activity_type_id, entity.uuid, True
|
||||
)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Constants for the Garmin Connect integration."""
|
||||
from datetime import timedelta
|
||||
from enum import Enum
|
||||
from typing import NamedTuple
|
||||
|
||||
from homeassistant.const import (
|
||||
LENGTH_METERS,
|
||||
@@ -160,7 +162,7 @@ GARMIN_ENTITY_LIST = {
|
||||
],
|
||||
"averageStressLevel": ["Avg Stress Level", "lvl", "mdi:flash-alert", None, SensorStateClass.TOTAL, True],
|
||||
"maxStressLevel": ["Max Stress Level", "lvl", "mdi:flash-alert", None, SensorStateClass.TOTAL, True],
|
||||
"stressQualifier": ["Stress Qualifier", None, "mdi:flash-alert", None, SensorStateClass.TOTAL, False],
|
||||
"stressQualifier": ["Stress Qualifier", None, "mdi:flash-alert", None, None, False],
|
||||
"stressDuration": ["Stress Duration", TIME_MINUTES, "mdi:flash-alert", None, SensorStateClass.TOTAL, False],
|
||||
"restStressDuration": [
|
||||
"Rest Stress Duration",
|
||||
@@ -389,14 +391,39 @@ GARMIN_ENTITY_LIST = {
|
||||
None,
|
||||
False,
|
||||
],
|
||||
"weight": ["Weight", MASS_KILOGRAMS, "mdi:weight-kilogram", SensorDeviceClass.WEIGHT, SensorStateClass.TOTAL, False],
|
||||
"weight": ["Weight", MASS_KILOGRAMS, "mdi:weight-kilogram", SensorDeviceClass.WEIGHT, SensorStateClass.MEASUREMENT, False],
|
||||
"bmi": ["BMI", "bmi", "mdi:food", None, SensorStateClass.TOTAL, False],
|
||||
"bodyFat": ["Body Fat", PERCENTAGE, "mdi:food", None, SensorStateClass.TOTAL, False],
|
||||
"bodyWater": ["Body Water", PERCENTAGE, "mdi:water-percent", None, SensorStateClass.TOTAL, False],
|
||||
"boneMass": ["Bone Mass", MASS_KILOGRAMS, "mdi:bone", SensorDeviceClass.WEIGHT, SensorStateClass.TOTAL, False],
|
||||
"muscleMass": ["Muscle Mass", MASS_KILOGRAMS, "mdi:dumbbell", SensorDeviceClass.WEIGHT, SensorStateClass.TOTAL, False],
|
||||
"boneMass": ["Bone Mass", MASS_KILOGRAMS, "mdi:bone", SensorDeviceClass.WEIGHT, SensorStateClass.MEASUREMENT, False],
|
||||
"muscleMass": ["Muscle Mass", MASS_KILOGRAMS, "mdi:dumbbell", SensorDeviceClass.WEIGHT, SensorStateClass.MEASUREMENT, False],
|
||||
"physiqueRating": ["Physique Rating", None, "mdi:numeric", None, SensorStateClass.TOTAL, False],
|
||||
"visceralFat": ["Visceral Fat", PERCENTAGE, "mdi:food", None, SensorStateClass.TOTAL, False],
|
||||
"metabolicAge": ["Metabolic Age", TIME_YEARS, "mdi:calendar-heart", None, SensorStateClass.TOTAL, False],
|
||||
"nextAlarm": ["Next Alarm Time", None, "mdi:alarm", SensorDeviceClass.TIMESTAMP, None, True],
|
||||
"lastActivities": ["Last Activities", None, "mdi:numeric", SensorStateClass.TOTAL, None, False]
|
||||
|
||||
}
|
||||
|
||||
GEAR_ICONS = {
|
||||
"Shoes": "mdi:shoe-sneaker",
|
||||
"Bike": "mdi:bike",
|
||||
"Other": "mdi:basketball",
|
||||
"Golf Clubs": "mdi:golf",
|
||||
}
|
||||
|
||||
|
||||
class SERVICE_SETTING(NamedTuple):
|
||||
"""Options for the service settings, see services.yaml"""
|
||||
|
||||
ONLY_THIS_AS_DEFAULT = "set this as default, unset others"
|
||||
DEFAULT = "set as default"
|
||||
UNSET_DEFAULT = "unset default"
|
||||
|
||||
|
||||
class GEAR(NamedTuple):
|
||||
UUID = "uuid"
|
||||
TYPE_KEY = "typeKey"
|
||||
TYPE_ID = "typeId"
|
||||
USERPROFILE_ID = "userProfileId"
|
||||
ACTIVITY_TYPE_PK = "activityTypePk"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"domain": "garmin_connect",
|
||||
"name": "Garmin Connect",
|
||||
"documentation": "https://github.com/cyberjunky/home-assistant-garmin_connect",
|
||||
"issue_tracker": "https://github.com/cyberjunky/home-assistant-garmin_connect/issues",
|
||||
"requirements": ["garminconnect==0.1.50"],
|
||||
"codeowners": ["@cyberjunky"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://github.com/cyberjunky/home-assistant-garmin_connect",
|
||||
"issue_tracker": "https://github.com/cyberjunky/home-assistant-garmin_connect/issues",
|
||||
"iot_class": "cloud_polling",
|
||||
"version": "0.2.8"
|
||||
"requirements": ["garminconnect==0.1.55", "tzlocal"],
|
||||
"version": "0.2.16"
|
||||
}
|
||||
|
||||
@@ -2,27 +2,41 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
from numbers import Number
|
||||
|
||||
import datetime
|
||||
import pytz
|
||||
from tzlocal import get_localzone
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorEntity,
|
||||
SensorDeviceClass,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
CONF_ID,
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
LENGTH_KILOMETERS,
|
||||
)
|
||||
from homeassistant.const import ATTR_ATTRIBUTION, CONF_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_platform
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
)
|
||||
|
||||
|
||||
from .alarm_util import calculate_next_active_alarms
|
||||
from .const import (
|
||||
DATA_COORDINATOR,
|
||||
DOMAIN as GARMIN_DOMAIN,
|
||||
GARMIN_ENTITY_LIST,
|
||||
GEAR,
|
||||
GEAR_ICONS,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -66,8 +80,35 @@ async def async_setup_entry(
|
||||
enabled_by_default,
|
||||
)
|
||||
)
|
||||
if "gear" in coordinator.data:
|
||||
for gear_item in coordinator.data["gear"]:
|
||||
entities.append(
|
||||
GarminConnectGearSensor(
|
||||
coordinator,
|
||||
unique_id,
|
||||
gear_item[GEAR.UUID],
|
||||
gear_item["gearTypeName"],
|
||||
gear_item["displayName"],
|
||||
None,
|
||||
True,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
platform = entity_platform.async_get_current_platform()
|
||||
|
||||
platform.async_register_entity_service(
|
||||
"set_active_gear", ENTITY_SERVICE_SCHEMA, coordinator.set_active_gear
|
||||
)
|
||||
|
||||
|
||||
ENTITY_SERVICE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_ENTITY_ID): str,
|
||||
vol.Required("activity_type"): str,
|
||||
vol.Required("setting"): str,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
@@ -104,6 +145,10 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state of the sensor."""
|
||||
|
||||
if self._type == "lastActivities":
|
||||
return len(self.coordinator.data[self._type])
|
||||
|
||||
if not self.coordinator.data or not self.coordinator.data[self._type]:
|
||||
return None
|
||||
|
||||
@@ -118,8 +163,8 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
)
|
||||
if active_alarms:
|
||||
date_time_obj = datetime.datetime.strptime(active_alarms[0], "%Y-%m-%dT%H:%M:%S")
|
||||
timezone = pytz.timezone('UTC')
|
||||
timezone_date_time_obj = timezone.localize(date_time_obj)
|
||||
tz = get_localzone()
|
||||
timezone_date_time_obj = date_time_obj.replace(tzinfo=tz)
|
||||
return timezone_date_time_obj
|
||||
else:
|
||||
return None
|
||||
@@ -128,11 +173,11 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
|
||||
if self._device_class == SensorDeviceClass.TIMESTAMP:
|
||||
date_time_obj = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
|
||||
timezone = pytz.timezone('UTC')
|
||||
timezone_date_time_obj = timezone.localize(date_time_obj)
|
||||
tz = get_localzone()
|
||||
timezone_date_time_obj = date_time_obj.replace(tzinfo=tz)
|
||||
return timezone_date_time_obj
|
||||
|
||||
return round(value, 2)
|
||||
return round(value, 2) if isinstance(value, Number) else value
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
@@ -143,6 +188,10 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
attributes = {
|
||||
"last_synced": self.coordinator.data["lastSyncTimestampGMT"],
|
||||
}
|
||||
|
||||
if self._type == "lastActivities":
|
||||
attributes["last_Activities"] = self.coordinator.data[self._type]
|
||||
|
||||
if self._type == "nextAlarm":
|
||||
attributes["next_alarms"] = calculate_next_active_alarms(
|
||||
self.coordinator.data[self._type]
|
||||
@@ -172,3 +221,134 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
|
||||
and self.coordinator.data
|
||||
and self._type in self.coordinator.data
|
||||
)
|
||||
|
||||
|
||||
class GarminConnectGearSensor(CoordinatorEntity, SensorEntity):
|
||||
"""Representation of a Garmin Connect Sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator,
|
||||
unique_id,
|
||||
uuid,
|
||||
sensor_type,
|
||||
name,
|
||||
device_class: None,
|
||||
enabled_default: bool = True,
|
||||
):
|
||||
"""Initialize a Garmin Connect sensor."""
|
||||
super().__init__(coordinator)
|
||||
|
||||
self._unique_id = unique_id
|
||||
self._type = sensor_type
|
||||
self._uuid = uuid
|
||||
self._device_class = device_class
|
||||
self._enabled_default = enabled_default
|
||||
|
||||
self._attr_name = name
|
||||
self._attr_device_class = self._device_class
|
||||
self._attr_icon = GEAR_ICONS[sensor_type]
|
||||
self._attr_native_unit_of_measurement = LENGTH_KILOMETERS
|
||||
self._attr_unique_id = f"{self._unique_id}_{self._uuid}"
|
||||
self._attr_state_class = SensorStateClass.TOTAL
|
||||
self._attr_device_class = "garmin_gear"
|
||||
|
||||
@property
|
||||
def uuid(self):
|
||||
"""Return the entity uuid"""
|
||||
return self._uuid
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state of the sensor."""
|
||||
if not self.coordinator.data or not self._stats():
|
||||
return None
|
||||
|
||||
value = self._stats()["totalDistance"]
|
||||
return round(value / 1000, 2)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return attributes for sensor."""
|
||||
gear = self._gear()
|
||||
stats = self._stats()
|
||||
gear_defaults = self._gear_defaults()
|
||||
activity_types = self.coordinator.data["activity_types"]
|
||||
default_for_activity = self._activity_names_for_gear_defaults(
|
||||
gear_defaults, activity_types
|
||||
)
|
||||
|
||||
if not self.coordinator.data or not gear or not stats:
|
||||
return {}
|
||||
|
||||
attributes = {
|
||||
"last_synced": self.coordinator.data["lastSyncTimestampGMT"],
|
||||
"total_activities": stats["totalActivities"],
|
||||
"create_date": stats["createDate"],
|
||||
"update_date": stats["updateDate"],
|
||||
"date_begin": gear["dateBegin"],
|
||||
"date_end": gear["dateEnd"],
|
||||
"gear_make_name": gear["gearMakeName"],
|
||||
"gear_model_name": gear["gearModelName"],
|
||||
"gear_status_name": gear["gearStatusName"],
|
||||
"custom_make_model": gear["customMakeModel"],
|
||||
"maximum_meters": gear["maximumMeters"],
|
||||
}
|
||||
|
||||
attributes["default_for_activity"] = (
|
||||
", ".join(default_for_activity) if default_for_activity else "None"
|
||||
)
|
||||
|
||||
return attributes
|
||||
|
||||
def _activity_names_for_gear_defaults(self, gear_defaults, activity_types):
|
||||
return list(
|
||||
map(
|
||||
lambda b: b["typeKey"],
|
||||
filter(
|
||||
lambda a: a["typeId"]
|
||||
in map(lambda d: d["activityTypePk"], gear_defaults),
|
||||
activity_types,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information."""
|
||||
return {
|
||||
"identifiers": {(GARMIN_DOMAIN, self._unique_id)},
|
||||
"name": "Garmin Connect",
|
||||
"manufacturer": "Garmin Connect",
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
return self._enabled_default
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return super().available and self.coordinator.data and self._gear()
|
||||
|
||||
def _stats(self):
|
||||
"""Get gear statistics from garmin"""
|
||||
for gear_stats_item in self.coordinator.data["gear_stats"]:
|
||||
if gear_stats_item[GEAR.UUID] == self._uuid:
|
||||
return gear_stats_item
|
||||
|
||||
def _gear(self):
|
||||
"""Get gear from garmin"""
|
||||
for gear_item in self.coordinator.data["gear"]:
|
||||
if gear_item[GEAR.UUID] == self._uuid:
|
||||
return gear_item
|
||||
|
||||
def _gear_defaults(self):
|
||||
"""Get gear defaults"""
|
||||
return list(
|
||||
filter(
|
||||
lambda d: d[GEAR.UUID] == self.uuid and d["defaultGear"] is True,
|
||||
self.coordinator.data["gear_defaults"],
|
||||
)
|
||||
)
|
||||
|
||||
39
custom_components/garmin_connect/services.yaml
Normal file
39
custom_components/garmin_connect/services.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
set_active_gear:
|
||||
name: Set active gear for activity
|
||||
# target:
|
||||
# entity:
|
||||
# integration: "garmin_connect"
|
||||
fields:
|
||||
activity_type:
|
||||
required: true
|
||||
name: activity type
|
||||
description: garmin activity type
|
||||
example: running
|
||||
default: running
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- running
|
||||
- cycling
|
||||
- hiking
|
||||
- other
|
||||
- walking
|
||||
- swimming
|
||||
setting:
|
||||
required: true
|
||||
name: setting
|
||||
description: gear setting to apply
|
||||
default: set this as default, unset others
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- set this as default, unset others
|
||||
- set as default
|
||||
- unset default
|
||||
entity_id:
|
||||
description: entity
|
||||
required: true
|
||||
selector:
|
||||
entity:
|
||||
integration: garmin_connect
|
||||
device_class: garmin_gear
|
||||
@@ -6,7 +6,7 @@
|
||||
"error": {
|
||||
"cannot_connect": "Falha na liga\u00e7\u00e3o",
|
||||
"invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida",
|
||||
"unknown": "Erro inesperado"
|
||||
"unknown": "Erro desconhecido"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
@@ -19,4 +19,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
custom_components/garmin_connect/translations/sk.json
Normal file
23
custom_components/garmin_connect/translations/sk.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Účet je už nakonfigurovaný"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Nepodarilo sa pripojiť",
|
||||
"invalid_auth": "Neplatné overenie",
|
||||
"too_many_requests": "Príliš veľa žiadostí, skúste to neskôr.",
|
||||
"unknown": "Neočakávaná chyba"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Heslo",
|
||||
"username": "Užívateľské meno"
|
||||
},
|
||||
"description": "Zadajte svoje poverenia.",
|
||||
"title": "Garmin Connect"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user