A Home Assistant custom integration for Husqvarna smart garden devices — supporting both the Gardena Smart System API and the Automower Connect API through a single integration. Device states are updated in real time via cloud WebSocket connections, with automatic fallback to polling if the connection is interrupted.
| Device | Platform(s) | Description |
|---|---|---|
| Smart Sensor | sensor |
Soil moisture, soil temperature, ambient temperature, light intensity |
| Smart Water Control | valve, sensor, binary_sensor |
Single-valve irrigation controller with open/close and timed watering |
| Smart Irrigation Control | valve, sensor, binary_sensor |
Multi-zone irrigation controller (up to 6 valves) |
| Smart Power Adapter | switch, sensor, binary_sensor |
Smart power outlet with on/off and timed control |
| SILENO Mower | lawn_mower, sensor, binary_sensor |
Robotic lawn mower with start, dock, pause, and schedule override |
All Gardena devices also expose common diagnostic sensors (battery level, RF signal strength) when the device reports them.
| Device | Platform(s) | Description |
|---|---|---|
| Husqvarna Automower | lawn_mower, sensor, binary_sensor, switch, number, device_tracker, calendar, event |
Full-featured robotic mower with GPS tracking, mowing schedules, work areas, stay-out zones, headlight control, cutting height adjustment, and state-transition events |
Note: SILENO mowers are supported through the Gardena Smart System API (above), not through the Automower Connect API. The Automower API is for Husqvarna Automower models (e.g., 305, 315, 405X, 435X AWD, 450X, NERA). Automowers do not require a Gardena Smart Gateway — they connect directly to the Husqvarna cloud.
Before installing this integration, you need to create an application on the Husqvarna Developer Portal to obtain API credentials.
- Go to the Husqvarna Developer Portal and create an account (or sign in with your existing Husqvarna account).
- Navigate to My Applications and click Create Application.
- Give it a name (e.g. "Home Assistant") and set the redirect URI to
https://localhost. - Under Connected APIs, enable the APIs you want to use:
- Gardena Smart System API — for Gardena sensors, valves, power sockets, and SILENO mowers
- Automower Connect API — for Husqvarna Automower robotic mowers
- You can enable both on the same application.
- Note the Application Key (Client ID) and Application Secret — you will need both during setup in Home Assistant.
- Open HACS in your Home Assistant UI.
- Go to Integrations and search for "Gardena Smart System".
- Click Download and restart Home Assistant.
Not finding it? If the integration isn't listed yet, add it as a custom repository: click the three-dot menu → Custom repositories, enter
https://github.com/kayloehmann/ha-gardena-smart-system, select Integration, then click Add.
- Download the latest release from the GitHub releases page.
- Copy the
custom_components/gardena_smart_systemfolder into your Home Assistantconfig/custom_components/directory. - Restart Home Assistant.
This integration is configured entirely through the Home Assistant UI. No YAML configuration is needed.
- Go to Settings > Devices & Services > Add Integration.
- Search for "Gardena Smart System" and select it.
- Enter your Application Key (Client ID) and Application Secret from the Husqvarna Developer Portal.
- Select the API you want to connect:
- Gardena Smart System — for Gardena devices (sensors, valves, power sockets, SILENO mowers)
- Automower Connect — for Husqvarna Automower robotic mowers
- For the Gardena Smart System API: if your account has multiple gardens (locations), you will be prompted to select which one to add. If you only have one garden, it is selected automatically.
- For the Automower Connect API: all mowers linked to your Husqvarna account are discovered automatically.
To use both Gardena and Automower devices, add the integration twice — once selecting "Gardena Smart System" and once selecting "Automower Connect". Both use the same application credentials.
If your credentials expire or become invalid, Home Assistant will prompt you to re-authenticate. Go to the integration page, click Reconfigure, and enter your updated credentials.
- Go to Settings > Devices & Services.
- Find the "Gardena Smart System" integration entry you want to remove.
- Click the three-dot menu and select Delete.
- All entities and devices created by this entry will be removed from Home Assistant.
If you installed via HACS, you can also uninstall the integration entirely:
- Open HACS, go to Integrations.
- Find "Gardena Smart System" and click Remove.
- Restart Home Assistant.
| Entity | Device Class | Unit | Category | Default |
|---|---|---|---|---|
| Battery | battery |
% | Diagnostic | Enabled |
| Battery state | enum |
-- | Diagnostic | Enabled |
| Signal strength | -- | % | Diagnostic | Disabled |
| Soil moisture | moisture |
% | -- | Enabled |
| Soil temperature | temperature |
°C | -- | Enabled |
| Ambient temperature | temperature |
°C | -- | Enabled |
| Light intensity | illuminance |
lx | -- | Enabled |
| Operating hours (mower) | -- | h | Diagnostic | Disabled |
| Activity (mower) | -- | -- | Diagnostic | Enabled |
| State (mower) | -- | -- | Diagnostic | Enabled |
| Last error code | -- | -- | Diagnostic | Disabled |
| Power socket remaining time | timestamp |
-- | -- | Enabled |
| Power socket state | -- | -- | Diagnostic | Enabled |
| Power socket last error | -- | -- | Diagnostic | Disabled |
| Remaining watering time (per valve) | timestamp |
-- | -- | Enabled |
| Valve error code (per valve) | -- | -- | Diagnostic | Disabled |
| Valve state (per valve) | -- | -- | Diagnostic | Enabled |
| Valve set error code | -- | -- | Diagnostic | Disabled |
| Entity | Device Class | Category | Default |
|---|---|---|---|
| Battery low | battery |
Diagnostic | Enabled |
| Valve error | problem |
Diagnostic | Enabled |
| Error (mower) | problem |
Diagnostic | Enabled |
| RF link | connectivity |
Diagnostic | Enabled |
| Entity | Device Class | Features |
|---|---|---|
| Valve | water |
Open, Close |
One valve entity is created per physical valve. Smart Water Control devices have a single valve, while Smart Irrigation Control devices create one valve entity per zone. Valve entities use the name configured in the Gardena app (e.g. "Rasen vorne"); if no name is set, they fall back to "Zone 1", "Zone 2", etc. Opening a valve starts watering for 60 minutes (default). Use the start_watering service for a custom duration.
Smart Irrigation Control — concurrent valve limit: The Smart Irrigation Control hardware allows at most 2 valves open at the same time per controller. The integration enforces this locally with a preflight check: if two valves on the same controller are already open, opening a third one is rejected immediately with a translated error message (
too_many_open_valves) — no failed API call, no silent half-states. Close one of the running valves first (or wait for its timer to expire). Standalone Smart Water Control devices are single-valve and not affected.
Remaining duration sensors (valve and power socket) display a live countdown in the HA frontend. When inactive, they show no value. If a new watering command is sent while the valve is already active (e.g. via start_watering), the countdown automatically adjusts to the new duration. The countdown uses the API-provided timestamp of when the duration was set, so it remains accurate even after a Home Assistant restart or integration reload.
| Entity | Device Class |
|---|---|
| Power | outlet |
Created for Gardena Smart Power Adapter devices. Supports turn on (indefinitely), turn off, and timed on via the turn_on_for service. The switch applies an optimistic local state update immediately after a successful API call, so the HA toggle flips instantly instead of waiting for the confirming WebSocket event — and the entity renders as a single toggle rather than two separate on/off buttons.
| Entity | Features |
|---|---|
| Mower | Start mowing, Dock, Pause |
Created for Gardena SILENO robotic mowers. Reports current activity: mowing, docked, paused, or error.
| Entity | Features |
|---|---|
| Mower | Start mowing, Dock, Pause |
Created for Husqvarna Automower robotic mowers. Reports current activity mapped to Home Assistant states:
| Automower Activity | HA State |
|---|---|
| MOWING, LEAVING, GOING_HOME | Mowing |
| CHARGING, PARKED_IN_CS | Docked |
| (state = PAUSED) | Paused |
| STOPPED_IN_GARDEN, (state = ERROR/FATAL_ERROR) | Error |
| Entity | Device Class | Unit | Category | Default |
|---|---|---|---|---|
| Battery | battery |
% | Diagnostic | Enabled |
| Cutting height | -- | -- | -- | Enabled |
| Next start | timestamp |
-- | -- | Enabled |
| Total cutting time | -- | h | Diagnostic | Enabled |
| Total charging time | -- | h | Diagnostic | Enabled |
| Charging cycles | -- | -- | Diagnostic | Enabled |
| Collisions | -- | -- | Diagnostic | Enabled |
| Total drive distance | -- | m | Diagnostic | Enabled |
| Blade usage time | -- | h | Diagnostic | Enabled |
| Total running time | -- | h | Diagnostic | Enabled |
| Total searching time | -- | h | Diagnostic | Enabled |
| Activity | enum |
-- | Diagnostic | Enabled |
| State | enum |
-- | Diagnostic | Enabled |
| Inactive reason | -- | -- | Diagnostic | Enabled |
| Restricted reason | enum |
-- | Diagnostic | Enabled |
| Error code | -- | -- | Diagnostic | Enabled |
| Last error time | timestamp |
-- | Diagnostic | Enabled |
| Schedule override | enum |
-- | Diagnostic | Enabled |
| Last seen | timestamp |
-- | Diagnostic | Enabled |
| Operating mode | enum |
-- | Diagnostic | Enabled |
Time-based statistics (cutting time, charging time, blade usage, running time, searching time) are reported by the API in seconds and converted to hours for display.
| Entity | Device Class | Category |
|---|---|---|
| Error | problem |
Diagnostic |
| Connected | connectivity |
Diagnostic |
Error is on when the mower is in ERROR or FATAL_ERROR state. Connected reflects the mower's cloud connectivity.
| Entity | Description |
|---|---|
| Headlight | Turn headlights always on or always off |
| Stay-out zone: {name} | Enable or disable individual stay-out zones |
| Work area: {name} | Enable or disable individual work areas |
Headlight, stay-out zone, and work area switches are only created if the mower model supports them (capability-based).
| Entity | Options | Description |
|---|---|---|
| Headlight mode | Always on, Always off, Evening only, Evening and night | Fine-grained headlight mode control |
The headlight mode select complements the simple on/off headlight switch with all four modes supported by the mower.
| Entity | Range | Step | Description |
|---|---|---|---|
| Cutting height | 1--9 | 1 | Global cutting height setting |
| Cutting height: {work area} | 0--100% | 1 | Per-work-area cutting height percentage |
Work area cutting height entities are only created if the mower supports work areas.
| Entity | Source Type | Default |
|---|---|---|
| Position | GPS | Disabled |
Shows the mower's latitude and longitude from the most recent GPS position. Only created for mower models with GPS capability. Disabled by default for privacy — enable it manually in the entity settings if you want GPS tracking.
| Entity | Description |
|---|---|
| Mowing schedule | Read-only calendar showing scheduled mowing tasks |
Each schedule task appears as a calendar event with the summary "Mowing" (or "Mowing (work area name)" for work-area-specific schedules).
| Entity | Description |
|---|---|
| Confirm error | Acknowledge and clear the current mower error |
Both Gardena and Automower devices expose event entities for state transitions, useful for automations.
| Entity | Events |
|---|---|
| Gardena Mower event | started_cutting, stopped, leaving, searching, charging, parked, paused, error, error_cleared |
| Gardena Valve event | started_watering, stopped_watering, error, error_cleared |
| Gardena Power socket event | turned_on, turned_off, error, error_cleared |
| Automower event | started_mowing, stopped, going_home, charging, leaving, parked, paused, error, error_cleared |
Each config entry creates a virtual "hub" device with integration-level diagnostic sensors.
| Entity | Description | Category |
|---|---|---|
| Device count | Number of devices managed by this entry | Diagnostic |
| Polling interval | Current polling interval in seconds | Diagnostic |
| API requests this month | Total API requests in the current calendar month | Diagnostic |
| API budget remaining | Remaining monthly API budget as a percentage | Diagnostic |
The integration tracks every API request (polls, WebSocket URL fetches, and device commands) and persists the monthly count across restarts. The budget assumes 10,000 requests/month per API — the standard Husqvarna rate limit when the API key is used exclusively for Home Assistant. The counter resets automatically at the start of each calendar month.
The API requests this month sensor also exposes month and budget as extra state attributes, making it easy to build dashboard cards or automations that warn when the budget is running low.
The integration registers three custom services for Gardena devices.
Start watering a valve for a specific duration, overriding any active schedule.
| Parameter | Type | Required | Description |
|---|---|---|---|
target |
entity | Yes | A valve entity from this integration |
duration |
number | Yes | Duration in minutes (1--1440) |
service: gardena_smart_system.start_watering
target:
entity_id: valve.garden_valve_1
data:
duration: 30Turn on a smart power socket for a specific duration.
| Parameter | Type | Required | Description |
|---|---|---|---|
target |
entity | Yes | A switch entity from this integration |
duration |
number | Yes | Duration in minutes (1--1440) |
service: gardena_smart_system.turn_on_for
target:
entity_id: switch.garden_power_socket
data:
duration: 120Force the mower to mow for a specific duration, ignoring its configured schedule.
| Parameter | Type | Required | Description |
|---|---|---|---|
target |
entity | Yes | A lawn_mower entity from this integration |
duration |
number | Yes | Duration in minutes (1--480) |
service: gardena_smart_system.override_schedule
target:
entity_id: lawn_mower.sileno_mower
data:
duration: 60Park the mower indefinitely. It will stay in the charging station until manually resumed.
| Parameter | Type | Required | Description |
|---|---|---|---|
target |
entity | Yes | A lawn_mower entity from this integration |
service: gardena_smart_system.park_until_further_notice
target:
entity_id: lawn_mower.automower_450x_mowerResume the mower's automatic mowing schedule.
| Parameter | Type | Required | Description |
|---|---|---|---|
target |
entity | Yes | A lawn_mower entity from this integration |
service: gardena_smart_system.resume_schedule
target:
entity_id: lawn_mower.automower_450x_mowerautomation:
- alias: "Water when soil moisture drops below 30%"
trigger:
- platform: numeric_state
entity_id: sensor.smart_sensor_moisture
below: 30
condition:
- condition: time
after: "06:00:00"
before: "09:00:00"
action:
- service: gardena_smart_system.start_watering
target:
entity_id: valve.garden_valve_1
data:
duration: 20automation:
- alias: "Notify on Automower error"
trigger:
- platform: state
entity_id: binary_sensor.automower_450x_error
to: "on"
action:
- service: notify.mobile_app
data:
title: "Automower Error"
message: >
The mower reported an error.
State: {{ states('sensor.automower_450x_state') }}
Error code: {{ states('sensor.automower_450x_error_code') }}automation:
- alias: "Park mower before rain"
trigger:
- platform: numeric_state
entity_id: sensor.openweathermap_forecast_precipitation_probability
above: 80
condition:
- condition: state
entity_id: lawn_mower.automower_450x_mower
state: "mowing"
action:
- service: lawn_mower.dock
target:
entity_id: lawn_mower.automower_450x_mowerautomation:
- alias: "Notify when blades need replacement"
trigger:
- platform: numeric_state
entity_id: sensor.automower_450x_blade_usage_time
above: 200
action:
- service: notify.mobile_app
data:
title: "Blade replacement needed"
message: "The Automower blades have been running for over 200 hours. Consider replacing them."Both APIs use the same architecture: real-time WebSocket push with REST polling fallback. Each API has its own independent connection and rate limit budget.
| # | API Call | Purpose |
|---|---|---|
| 1 | POST /oauth2/token |
Acquire an OAuth2 access token |
| 2 | GET /locations/{id} |
Fetch all devices and their current state |
| 3 | POST /websocket |
Request a WebSocket URL for real-time updates |
| 4 | WebSocket connect | Open the persistent connection for push updates |
That is 3 REST calls + 1 WebSocket connection per startup.
| API Call | Frequency | Purpose |
|---|---|---|
GET /locations/{id} |
Every 1 hour | Health-check poll — verifies the device list is in sync and detects newly added devices |
POST /oauth2/token |
Every ~55 minutes | Token refresh (tokens expire after 1 hour; on a separate endpoint that does not count against the Smart API quota) |
| WebSocket messages | Continuous (push) | All device state updates arrive here at zero REST cost |
Daily total: ~24 health-check polls/day — roughly 7% of the monthly budget.
| API Call | Frequency | Purpose |
|---|---|---|
GET /locations/{id} |
Every 5 minutes | Poll for device state (matches Gardena sensor hardware update frequency) |
POST /oauth2/token |
Every ~55 minutes | Token refresh (separate endpoint) |
Daily total: ~288 polls/day — roughly 86% of the monthly budget. This aggressive fallback ensures near-real-time sensor data even without WebSocket, while still leaving headroom for commands and reconnect attempts.
| # | API Call | Purpose |
|---|---|---|
| 1 | POST /oauth2/token |
Acquire an OAuth2 access token (shared auth) |
| 2 | GET /mowers |
Fetch all mowers and their current state |
| 3 | WebSocket connect | Open the persistent connection for push updates |
| API Call | Frequency | Purpose |
|---|---|---|
GET /mowers |
Every 1 hour | Health-check poll |
POST /oauth2/token |
Every ~55 minutes | Token refresh (separate endpoint) |
| WebSocket messages | Continuous (push) | All mower state updates |
Daily total: ~24 health-check polls/day — roughly 7% of the monthly budget.
| API Call | Frequency | Purpose |
|---|---|---|
GET /mowers |
Every 5 minutes | Poll for mower state |
POST /oauth2/token |
Every ~55 minutes | Token refresh (separate endpoint) |
Daily total: ~288 polls/day — roughly 86% of the monthly budget.
After receiving HTTP 429, both coordinators use graduated backoff: 5 min → 10 min → 20 min → 40 min → 60 min (max). Each consecutive rate limit doubles the wait. A successful API response resets the counter.
| API Call | Frequency | Purpose |
|---|---|---|
PUT /command/{id} (Gardena) |
On demand, token bucket (10, refill 1/5 s) | Valve, switch, mower commands |
POST /mowers/{id}/actions (Automower) |
On demand, token bucket (10, refill 1/5 s) | Mower actions (start, pause, park) |
PATCH /mowers/{id}/settings (Automower) |
On demand, token bucket (10, refill 1/5 s) | Cutting height, headlight, stay-out zones |
Each button press or automation action is one API call. A token-bucket throttle (10 tokens, refilling at 1 per 5 s) allows small bursts (e.g. opening several valves) while capping the long-term rate at 1 command per 5 seconds.
| Strategy | Detail |
|---|---|
| WebSocket-first architecture | Device state updates arrive in real time via persistent WebSocket connections. REST API polling is only a fallback. If the WebSocket drops, the outer reconnect loop attempts reconnection 3 times over ~20 minutes (60 s → 5 min → 15 min), each time fetching a fresh signed WS URL. A watchdog timer checks every 60 seconds that the WebSocket is still receiving data — if silent for 5 minutes, the connection is forcibly recycled. |
| Single-use WebSocket URLs | Husqvarna's signed WS URLs are single-use — once rejected (e.g. HTTP 410), retrying the same URL is pointless. The library WebSocket client escalates any failure immediately to the coordinator instead of burning time and bandwidth on the dead URL. A fresh URL is fetched on each new connect attempt. |
| WebSocket URL caching | The freshly fetched WebSocket URL is cached and reused within one connect attempt as long as the auth token is still valid. The cache is invalidated when the token expires or a connection attempt fails. |
| Connect guard | An async lock prevents parallel WebSocket connect attempts (e.g. watchdog and poll cycle racing), avoiding duplicate API calls. |
| Circuit breaker | After 3 consecutive WebSocket start failures the integration enters a 15-minute cooldown during which no new WebSocket connection is attempted (REST polling continues uninterrupted). The cooldown escalates to 30 minutes after 5 failures and 60 minutes after 7+. A successful connection resets the counter. This protects the monthly API budget when Husqvarna's WebSocket endpoint has a bad day and would otherwise trigger a reconnect storm. Auth errors bypass the circuit breaker and trigger reauth instead. |
| Adaptive polling interval | When WebSocket is connected: 1-hour health-check only. When WebSocket drops: 5-minute polling (matches sensor hardware update rate, uses ~86% of monthly budget at worst). |
| Graduated rate limit backoff | If any API call returns HTTP 429 — including token refresh and WebSocket URL requests — polling backs off exponentially (5 min → 10 → 20 → 40 → 60 min max) and resets after a successful response. |
| Command throttling (token bucket) | A token bucket of 10 commands refills at 1 token per 5 seconds. This allows small bursts (e.g. opening several irrigation valves in a row) while keeping the long-term steady-state rate at ≤1 command / 5 s to protect the monthly API quota. |
| Auto-stop safety net | Once the monthly API budget drops below 5 % remaining (fewer than 500 of the 10 000 requests), the coordinator automatically pauses REST polls, WebSocket (re)connect attempts, and user-issued commands — the latter return a translated error (api_budget_exhausted). Normal operation resumes automatically on the next calendar month, or the user can create a fresh Husqvarna application to reset the budget. Protects against runaway scenarios (e.g. an unforeseen reconnect storm) from exhausting the quota 100 % and getting the API key hard-blocked for the rest of the month. |
| Independent budgets | Both the Gardena API and the Automower API allow ~10,000 requests/month each. Using one does not affect the other. |
- Don't restart Home Assistant frequently. Each restart triggers a full API poll and a new WebSocket connection request.
- Avoid rapid-fire automations. If you have automations that send multiple commands in a loop, add delays between them. The integration enforces a 5-second minimum, but longer pauses are better for quota.
- Use a dedicated API key for Home Assistant. The budget tracking sensors assume the full 10,000 requests/month are available exclusively for this integration. If you share the same Husqvarna application credentials with another smart home platform, they consume from the same quota and the budget percentage will be inaccurate. Create a separate application on the Husqvarna Developer Portal for each system.
- Use one integration instance per API. Each additional instance adds its own polling and WebSocket overhead.
- Monitor for rate limit warnings. Check the Home Assistant logs for messages containing "Rate limited" — this applies to both APIs.
- The integration logs a warning (e.g.,
Rate limited by Gardena API (hit #1), backing off to 0:05:00). - The polling interval increases with graduated backoff: 5 min → 10 min → 20 min → 40 min → 60 min (max).
- Existing entity states remain available (cached from the last successful update and WebSocket messages).
- Commands may fail until the rate limit resets.
- After a successful API response, the backoff counter resets and the normal polling interval is restored automatically.
- If the monthly budget has been almost fully consumed (< 5 % remaining), the auto-stop safety net takes over: polls, WS reconnects, and commands are refused until the calendar month rolls over. The API budget remaining hub sensor surfaces the current percentage so you can build an automation that warns you well before the auto-stop triggers.
The integration can optionally mirror all device states to a local MQTT broker. This is useful for local automations (Node-RED), cross-system integrations, or offline state caching.
- Ensure the MQTT integration is configured in Home Assistant.
- Go to Settings → Devices & Services → Gardena Smart System → Configure.
- Enable MQTT bridge and configure the topic prefix.
| Topic | Direction | Description |
|---|---|---|
{prefix}/{device_id}/state |
Outbound | Full device state as JSON (retained) |
{prefix}/{device_id}/availability |
Outbound | online or offline (retained) |
{prefix}/{device_id}/command |
Inbound | JSON command payload |
Publish a JSON payload to {prefix}/{device_id}/command:
{"action": "start_watering", "duration": 30, "service_id": "device-uuid:1"}| Action | Parameters | Description |
|---|---|---|
start_watering |
duration (minutes, default 60), service_id |
Start valve watering |
stop_watering |
service_id |
Stop valve |
turn_on |
duration (minutes, default 60), service_id |
Turn on power socket |
turn_off |
service_id |
Turn off power socket |
park |
service_id |
Park mower until further notice |
resume |
service_id |
Resume mower schedule |
Note: The MQTT bridge does not eliminate the cloud dependency. Device commands are still forwarded through the Husqvarna API. The bridge provides a local event bus for consuming state updates and triggering commands from external systems.
- Cloud-only: Both APIs communicate through the Husqvarna cloud. An active internet connection is required.
- API rate limits: See the API Rate Limits section above.
- Valve position: Gardena valves do not report percentage-based position — only open/closed state.
- Mower GPS (Gardena): The Gardena Smart System API does not expose GPS coordinates. GPS tracking is available only for Automower devices via the Automower Connect API.
- Calendar (Automower): The mowing schedule calendar is read-only. To modify schedules, use the Husqvarna Automower app.
- SILENO via Automower API: SILENO mowers are only supported through the Gardena Smart System API, not the Automower Connect API.
- Double-check that you are entering the Application Key and Application Secret from the Husqvarna Developer Portal (not your Husqvarna account username/password).
- Verify that your Gardena/Husqvarna account is linked properly.
- Ensure the correct API is connected to your application in the Husqvarna Developer Portal:
- For Gardena devices: enable the Gardena Smart System API
- For Automower: enable the Automower Connect API
- Go to the Husqvarna Developer Portal, open your application, and enable the Automower Connect API under Connected APIs.
- Gardena devices: The device may be out of RF range of the Gardena Smart Gateway. Check that the gateway is powered on and connected to your network.
- Automower: The mower may be out of cellular/Wi-Fi range. Check connectivity in the Husqvarna Automower app.
- Battery-powered devices may go offline when the battery is depleted.
This indicates the WebSocket connection to the Husqvarna cloud has failed. The integration continues to work via polling but updates will be delayed.
- A watchdog timer monitors the WebSocket connection and detects silent failures within 5 minutes. When triggered, it forces a reconnect and an immediate data refresh.
- The integration also automatically reconnects with graduated backoff (60 s → 5 min → 15 min, 3 attempts). After 3 consecutive failures the circuit breaker activates a 15-minute cooldown (30 min after 5 failures, 60 min after 7+). REST polling continues uninterrupted during the cooldown. No manual action is required.
- The repair issue resolves itself once reconnected.
- If it persists, check your Home Assistant host's internet connection or the Husqvarna service status for outages.
- The device may be temporarily unreachable. Wait a moment and try again.
- If the error persists, check the Home Assistant logs for details.
- Verify the device is online in the Gardena Smart App or Husqvarna Automower app.
- The integration uses a token-bucket throttle (10 commands, refilling at 1 per 5 s). Short bursts (e.g. opening several valves at once) are allowed; the warning only appears when an automation has already fired 10+ commands in quick succession.
- If you see this in automations, add a
delaystep between consecutive service calls, or spread them out further.
- The Husqvarna API has temporarily blocked your API key due to too many requests.
- The integration automatically backs off and will recover on its own.
- If this happens frequently, review your automations and restart habits. See API Rate Limits for tips.
This integration targets the Home Assistant Integration Quality Scale at the Platinum level.
| Tier | Rules | Status |
|---|---|---|
| Bronze | 19 | Passed (2 N/A for custom integrations) |
| Silver | 10 | Passed |
| Gold | 22 | Passed (2 N/A: discovery / discovery-update-info — cloud API, no local discovery) |
| Platinum | 3 | Passed |
Key quality features:
- 99% test coverage across 695 automated tests
- mypy --strict passes with zero errors on all 33 source files
- PEP 561 compliant (
py.typedmarkers on both client libraries) - Full async codebase — no blocking I/O in the event loop
- WebSocket session injection —
aiohttp.ClientSessionprovided by Home Assistant, not created internally - Diagnostics with sensitive data redaction (credentials, serial numbers, GPS coordinates, device names)
- Security hardening — STRIDE threat model audit, WebSocket error isolation, log truncation, OAuth token revocation on shutdown
- Repair issues for WebSocket connection loss
- Stale device cleanup — devices removed from the API are automatically removed from the HA device registry
- Translated exceptions — all error messages use the HA translation framework
The integration is fully translated into 31 languages:
| Language | Code | Language | Code |
|---|---|---|---|
| English | en |
Portuguese (BR) | pt-BR |
| German | de |
Russian | ru |
| French | fr |
Ukrainian | uk |
| Dutch | nl |
Czech | cs |
| Swedish | sv |
Slovak | sk |
| Italian | it |
Hungarian | hu |
| Spanish | es |
Romanian | ro |
| Danish | da |
Greek | el |
| Polish | pl |
Bulgarian | bg |
| Portuguese | pt |
Finnish | fi |
| Norwegian | nb |
Croatian | hr |
| Slovenian | sl |
Estonian | et |
| Latvian | lv |
Lithuanian | lt |
| Turkish | tr |
Catalan | ca |
| Chinese (Simplified) | zh-Hans |
Chinese (Traditional) | zh-Hant |
| Japanese | ja |
Translations cover all entity names, config flow text, options, services, error messages, and enum state labels.
This project is licensed under the MIT License. See LICENSE for details.