Added add gear to activity service, added gear_uuid attribute to gear sensors

This commit is contained in:
Ron Klinkien
2026-01-03 18:03:35 +01:00
parent 9ea284bf95
commit a81d4f955d
6 changed files with 104 additions and 5 deletions

View File

@@ -197,7 +197,7 @@ data:
See the action template for other available values to add. See the action template for other available values to add.
**Full Automation Example (Withings to Garmin):** **Withings scale data to Garmin**
```yaml ```yaml
alias: WithingsToGarmin alias: WithingsToGarmin
@@ -229,7 +229,7 @@ mode: single
```yaml ```yaml
action: garmin_connect.set_active_gear action: garmin_connect.set_active_gear
target: target:
entity_id: sensor.garmin_connect_adidas_running_shoes entity_id: sensor.garmin_connect_adidas
data: data:
activity_type: running activity_type: running
setting: set as default setting: set as default
@@ -247,7 +247,7 @@ data:
notes: Measured with Beurer BC54 notes: Measured with Beurer BC54
``` ```
### Create Activity **Create Activity**
Creates an activity in Garmin Connect: Creates an activity in Garmin Connect:
@@ -261,14 +261,43 @@ data:
distance_km: 5.0 distance_km: 5.0
``` ```
### Upload Activity **Upload Activity**
Uploads an activity file (FIT, GPX, TCX) to Garmin Connect: Uploads an activity file (FIT, GPX, TCX) to Garmin Connect:
```yaml ```yaml
action: garmin_connect.upload_activity action: garmin_connect.upload_activity
data: data:
file_path: "/config/activities/run.fit" file_path: "morning_run.fit"
```
**Add Gear to Activity**
Associates gear (shoes, bike, etc.) with a specific activity:
```yaml
action: garmin_connect.add_gear_to_activity
data:
activity_id: 12345678901
gear_uuid: "abc12345-def6-7890-ghij-klmn12345678"
```
**Automatically assign alternate running shoes after a run**
```yaml
automation:
- alias: "Assign alternate shoes to last running activity"
trigger:
- platform: state
entity_id: sensor.garmin_connect_last_activity
condition:
- condition: template
value_template: "{{ state_attr('sensor.garmin_connect_last_activity', 'activityType') == 'running' }}"
action:
- service: garmin_connect.add_gear_to_activity
data:
activity_id: "{{ state_attr('sensor.garmin_connect_last_activity', 'activityId') }}"
gear_uuid: "{{ state_attr('sensor.garmnin_connect_adidas', 'gear_uuid') }}"
``` ```
### Enable Debug Logging ### Enable Debug Logging

View File

@@ -267,6 +267,7 @@ class GarminConnectGearSensor(CoordinatorEntity, SensorEntity):
return {} return {}
attributes = { attributes = {
"gear_uuid": self._uuid,
"last_synced": self.coordinator.data["lastSyncTimestampGMT"], "last_synced": self.coordinator.data["lastSyncTimestampGMT"],
"total_activities": stats["totalActivities"], "total_activities": stats["totalActivities"],
"create_date": stats["createDate"], "create_date": stats["createDate"],

View File

@@ -68,6 +68,14 @@ UPLOAD_ACTIVITY_SCHEMA = vol.Schema(
} }
) )
SERVICE_ADD_GEAR_TO_ACTIVITY = "add_gear_to_activity"
ADD_GEAR_TO_ACTIVITY_SCHEMA = vol.Schema(
{
vol.Required("activity_id"): vol.Coerce(int),
vol.Required("gear_uuid"): cv.string,
}
)
def _get_coordinator(hass: HomeAssistant) -> GarminConnectDataUpdateCoordinator: def _get_coordinator(hass: HomeAssistant) -> GarminConnectDataUpdateCoordinator:
"""Get the first available coordinator from config entries.""" """Get the first available coordinator from config entries."""
@@ -243,6 +251,32 @@ async def async_setup_services(hass: HomeAssistant) -> None:
translation_placeholders={"error": str(err)}, translation_placeholders={"error": str(err)},
) from err ) from err
async def handle_add_gear_to_activity(call: ServiceCall) -> None:
"""Handle add_gear_to_activity service call."""
coordinator = _get_coordinator(hass)
activity_id = call.data.get("activity_id")
gear_uuid = call.data.get("gear_uuid")
if not await coordinator.async_login():
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="login_failed",
)
try:
await hass.async_add_executor_job(
coordinator.api.add_gear_to_activity,
gear_uuid,
activity_id,
)
except Exception as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="add_gear_to_activity_failed",
translation_placeholders={"error": str(err)},
) from err
# Register services # Register services
hass.services.async_register( hass.services.async_register(
DOMAIN, DOMAIN,
@@ -272,6 +306,13 @@ async def async_setup_services(hass: HomeAssistant) -> None:
schema=UPLOAD_ACTIVITY_SCHEMA, schema=UPLOAD_ACTIVITY_SCHEMA,
) )
hass.services.async_register(
DOMAIN,
SERVICE_ADD_GEAR_TO_ACTIVITY,
handle_add_gear_to_activity,
schema=ADD_GEAR_TO_ACTIVITY_SCHEMA,
)
async def async_unload_services(hass: HomeAssistant) -> None: async def async_unload_services(hass: HomeAssistant) -> None:
"""Unload Garmin Connect services.""" """Unload Garmin Connect services."""
@@ -279,3 +320,4 @@ async def async_unload_services(hass: HomeAssistant) -> None:
hass.services.async_remove(DOMAIN, SERVICE_ADD_BLOOD_PRESSURE) hass.services.async_remove(DOMAIN, SERVICE_ADD_BLOOD_PRESSURE)
hass.services.async_remove(DOMAIN, SERVICE_CREATE_ACTIVITY) hass.services.async_remove(DOMAIN, SERVICE_CREATE_ACTIVITY)
hass.services.async_remove(DOMAIN, SERVICE_UPLOAD_ACTIVITY) hass.services.async_remove(DOMAIN, SERVICE_UPLOAD_ACTIVITY)
hass.services.async_remove(DOMAIN, SERVICE_ADD_GEAR_TO_ACTIVITY)

View File

@@ -299,5 +299,26 @@ upload_activity:
description: Path to the activity file on the Home Assistant system. description: Path to the activity file on the Home Assistant system.
required: true required: true
example: "/config/activities/run.fit" example: "/config/activities/run.fit"
selector:
text:
add_gear_to_activity:
name: Add gear to activity
description: Associate gear (shoes, bike, etc.) with a specific activity.
fields:
activity_id:
name: Activity ID
description: The ID of the activity to add the gear to.
required: true
example: 12345678901
selector:
number:
min: 1
mode: box
gear_uuid:
name: Gear UUID
description: The UUID of the gear to add. Find this in the gear sensor attributes.
required: true
example: "abc12345-def6-7890-ghij-klmn12345678"
selector: selector:
text: text:

View File

@@ -61,6 +61,9 @@
}, },
"file_not_found": { "file_not_found": {
"message": "File not found: {file_path}" "message": "File not found: {file_path}"
},
"add_gear_to_activity_failed": {
"message": "Failed to add gear to activity: {error}"
} }
} }
} }

View File

@@ -423,6 +423,9 @@
}, },
"file_not_found": { "file_not_found": {
"message": "File not found: {file_path}" "message": "File not found: {file_path}"
},
"add_gear_to_activity_failed": {
"message": "Failed to add gear to activity: {error}"
} }
} }
} }