mirror of
https://github.com/home-assistant/core.git
synced 2025-09-10 07:11:37 +02:00
Add event platform to Husqvarna Automower (#148212)
Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
@@ -21,6 +21,7 @@ PLATFORMS: list[Platform] = [
|
|||||||
Platform.BUTTON,
|
Platform.BUTTON,
|
||||||
Platform.CALENDAR,
|
Platform.CALENDAR,
|
||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
|
Platform.EVENT,
|
||||||
Platform.LAWN_MOWER,
|
Platform.LAWN_MOWER,
|
||||||
Platform.NUMBER,
|
Platform.NUMBER,
|
||||||
Platform.SELECT,
|
Platform.SELECT,
|
||||||
|
@@ -17,3 +17,128 @@ ERROR_STATES = [
|
|||||||
MowerStates.WAIT_POWER_UP,
|
MowerStates.WAIT_POWER_UP,
|
||||||
MowerStates.WAIT_UPDATING,
|
MowerStates.WAIT_UPDATING,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
ERROR_KEYS = [
|
||||||
|
"alarm_mower_in_motion",
|
||||||
|
"alarm_mower_lifted",
|
||||||
|
"alarm_mower_stopped",
|
||||||
|
"alarm_mower_switched_off",
|
||||||
|
"alarm_mower_tilted",
|
||||||
|
"alarm_outside_geofence",
|
||||||
|
"angular_sensor_problem",
|
||||||
|
"battery_problem",
|
||||||
|
"battery_restriction_due_to_ambient_temperature",
|
||||||
|
"can_error",
|
||||||
|
"charging_current_too_high",
|
||||||
|
"charging_station_blocked",
|
||||||
|
"charging_system_problem",
|
||||||
|
"collision_sensor_defect",
|
||||||
|
"collision_sensor_error",
|
||||||
|
"collision_sensor_problem_front",
|
||||||
|
"collision_sensor_problem_rear",
|
||||||
|
"com_board_not_available",
|
||||||
|
"communication_circuit_board_sw_must_be_updated",
|
||||||
|
"complex_working_area",
|
||||||
|
"connection_changed",
|
||||||
|
"connection_not_changed",
|
||||||
|
"connectivity_problem",
|
||||||
|
"connectivity_settings_restored",
|
||||||
|
"cutting_drive_motor_1_defect",
|
||||||
|
"cutting_drive_motor_2_defect",
|
||||||
|
"cutting_drive_motor_3_defect",
|
||||||
|
"cutting_height_blocked",
|
||||||
|
"cutting_height_problem",
|
||||||
|
"cutting_height_problem_curr",
|
||||||
|
"cutting_height_problem_dir",
|
||||||
|
"cutting_height_problem_drive",
|
||||||
|
"cutting_motor_problem",
|
||||||
|
"cutting_stopped_slope_too_steep",
|
||||||
|
"cutting_system_blocked",
|
||||||
|
"cutting_system_imbalance_warning",
|
||||||
|
"cutting_system_major_imbalance",
|
||||||
|
"destination_not_reachable",
|
||||||
|
"difficult_finding_home",
|
||||||
|
"docking_sensor_defect",
|
||||||
|
"electronic_problem",
|
||||||
|
"empty_battery",
|
||||||
|
"folding_cutting_deck_sensor_defect",
|
||||||
|
"folding_sensor_activated",
|
||||||
|
"geofence_problem",
|
||||||
|
"gps_navigation_problem",
|
||||||
|
"guide_1_not_found",
|
||||||
|
"guide_2_not_found",
|
||||||
|
"guide_3_not_found",
|
||||||
|
"guide_calibration_accomplished",
|
||||||
|
"guide_calibration_failed",
|
||||||
|
"high_charging_power_loss",
|
||||||
|
"high_internal_power_loss",
|
||||||
|
"high_internal_temperature",
|
||||||
|
"internal_voltage_error",
|
||||||
|
"invalid_battery_combination_invalid_combination_of_different_battery_types",
|
||||||
|
"invalid_sub_device_combination",
|
||||||
|
"invalid_system_configuration",
|
||||||
|
"left_brush_motor_overloaded",
|
||||||
|
"lift_sensor_defect",
|
||||||
|
"lifted",
|
||||||
|
"limited_cutting_height_range",
|
||||||
|
"loop_sensor_defect",
|
||||||
|
"loop_sensor_problem_front",
|
||||||
|
"loop_sensor_problem_left",
|
||||||
|
"loop_sensor_problem_rear",
|
||||||
|
"loop_sensor_problem_right",
|
||||||
|
"low_battery",
|
||||||
|
"memory_circuit_problem",
|
||||||
|
"mower_lifted",
|
||||||
|
"mower_tilted",
|
||||||
|
"no_accurate_position_from_satellites",
|
||||||
|
"no_confirmed_position",
|
||||||
|
"no_drive",
|
||||||
|
"no_loop_signal",
|
||||||
|
"no_power_in_charging_station",
|
||||||
|
"no_response_from_charger",
|
||||||
|
"outside_working_area",
|
||||||
|
"poor_signal_quality",
|
||||||
|
"reference_station_communication_problem",
|
||||||
|
"right_brush_motor_overloaded",
|
||||||
|
"safety_function_faulty",
|
||||||
|
"settings_restored",
|
||||||
|
"sim_card_locked",
|
||||||
|
"sim_card_not_found",
|
||||||
|
"sim_card_requires_pin",
|
||||||
|
"slipped_mower_has_slipped_situation_not_solved_with_moving_pattern",
|
||||||
|
"slope_too_steep",
|
||||||
|
"sms_could_not_be_sent",
|
||||||
|
"stop_button_problem",
|
||||||
|
"stuck_in_charging_station",
|
||||||
|
"switch_cord_problem",
|
||||||
|
"temporary_battery_problem",
|
||||||
|
"tilt_sensor_problem",
|
||||||
|
"too_high_discharge_current",
|
||||||
|
"too_high_internal_current",
|
||||||
|
"trapped",
|
||||||
|
"ultrasonic_problem",
|
||||||
|
"ultrasonic_sensor_1_defect",
|
||||||
|
"ultrasonic_sensor_2_defect",
|
||||||
|
"ultrasonic_sensor_3_defect",
|
||||||
|
"ultrasonic_sensor_4_defect",
|
||||||
|
"unexpected_cutting_height_adj",
|
||||||
|
"unexpected_error",
|
||||||
|
"upside_down",
|
||||||
|
"weak_gps_signal",
|
||||||
|
"wheel_drive_problem_left",
|
||||||
|
"wheel_drive_problem_rear_left",
|
||||||
|
"wheel_drive_problem_rear_right",
|
||||||
|
"wheel_drive_problem_right",
|
||||||
|
"wheel_motor_blocked_left",
|
||||||
|
"wheel_motor_blocked_rear_left",
|
||||||
|
"wheel_motor_blocked_rear_right",
|
||||||
|
"wheel_motor_blocked_right",
|
||||||
|
"wheel_motor_overloaded_left",
|
||||||
|
"wheel_motor_overloaded_rear_left",
|
||||||
|
"wheel_motor_overloaded_rear_right",
|
||||||
|
"wheel_motor_overloaded_right",
|
||||||
|
"work_area_not_valid",
|
||||||
|
"wrong_loop_signal",
|
||||||
|
"wrong_pin_code",
|
||||||
|
"zone_generator_problem",
|
||||||
|
]
|
||||||
|
108
homeassistant/components/husqvarna_automower/event.py
Normal file
108
homeassistant/components/husqvarna_automower/event.py
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
"""Creates the event entities for supported mowers."""
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
|
from aioautomower.model import SingleMessageData
|
||||||
|
|
||||||
|
from homeassistant.components.event import (
|
||||||
|
DOMAIN as EVENT_DOMAIN,
|
||||||
|
EventEntity,
|
||||||
|
EventEntityDescription,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
|
from . import AutomowerConfigEntry
|
||||||
|
from .const import ERROR_KEYS
|
||||||
|
from .coordinator import AutomowerDataUpdateCoordinator
|
||||||
|
from .entity import AutomowerBaseEntity
|
||||||
|
|
||||||
|
PARALLEL_UPDATES = 1
|
||||||
|
|
||||||
|
ATTR_SEVERITY = "severity"
|
||||||
|
ATTR_LATITUDE = "latitude"
|
||||||
|
ATTR_LONGITUDE = "longitude"
|
||||||
|
ATTR_DATE_TIME = "date_time"
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: AutomowerConfigEntry,
|
||||||
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up Automower message event entities.
|
||||||
|
|
||||||
|
Entities are created dynamically based on messages received from the API,
|
||||||
|
but only for mowers that support message events.
|
||||||
|
"""
|
||||||
|
coordinator = config_entry.runtime_data
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
|
restored_mowers = {
|
||||||
|
entry.unique_id.removesuffix("_message")
|
||||||
|
for entry in er.async_entries_for_config_entry(
|
||||||
|
entity_registry, config_entry.entry_id
|
||||||
|
)
|
||||||
|
if entry.domain == EVENT_DOMAIN
|
||||||
|
}
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
AutomowerMessageEventEntity(mower_id, coordinator)
|
||||||
|
for mower_id in restored_mowers
|
||||||
|
if mower_id in coordinator.data
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle_message(msg: SingleMessageData) -> None:
|
||||||
|
if msg.id in restored_mowers:
|
||||||
|
return
|
||||||
|
|
||||||
|
restored_mowers.add(msg.id)
|
||||||
|
async_add_entities([AutomowerMessageEventEntity(msg.id, coordinator)])
|
||||||
|
|
||||||
|
coordinator.api.register_single_message_callback(_handle_message)
|
||||||
|
|
||||||
|
|
||||||
|
class AutomowerMessageEventEntity(AutomowerBaseEntity, EventEntity):
|
||||||
|
"""EventEntity for Automower message events."""
|
||||||
|
|
||||||
|
entity_description: EventEntityDescription
|
||||||
|
_message_cb: Callable[[SingleMessageData], None]
|
||||||
|
_attr_translation_key = "message"
|
||||||
|
_attr_event_types = ERROR_KEYS
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
mower_id: str,
|
||||||
|
coordinator: AutomowerDataUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize Automower message event entity."""
|
||||||
|
super().__init__(mower_id, coordinator)
|
||||||
|
self._attr_unique_id = f"{mower_id}_message"
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle(self, msg: SingleMessageData) -> None:
|
||||||
|
"""Handle a message event from the API and trigger the event entity if it matches the entity's mower ID."""
|
||||||
|
if msg.id != self.mower_id:
|
||||||
|
return
|
||||||
|
message = msg.attributes.message
|
||||||
|
self._trigger_event(
|
||||||
|
message.code,
|
||||||
|
{
|
||||||
|
ATTR_SEVERITY: message.severity,
|
||||||
|
ATTR_LATITUDE: message.latitude,
|
||||||
|
ATTR_LONGITUDE: message.longitude,
|
||||||
|
ATTR_DATE_TIME: message.time,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Register callback when entity is added to hass."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
self.coordinator.api.register_single_message_callback(self._handle)
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Unregister WebSocket callback when entity is removed."""
|
||||||
|
self.coordinator.api.unregister_single_message_callback(self._handle)
|
@@ -13,6 +13,11 @@
|
|||||||
"default": "mdi:saw-blade"
|
"default": "mdi:saw-blade"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"event": {
|
||||||
|
"message": {
|
||||||
|
"default": "mdi:alert-circle-check-outline"
|
||||||
|
}
|
||||||
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"cutting_height": {
|
"cutting_height": {
|
||||||
"default": "mdi:grass"
|
"default": "mdi:grass"
|
||||||
|
@@ -28,7 +28,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
from . import AutomowerConfigEntry
|
from . import AutomowerConfigEntry
|
||||||
from .const import ERROR_STATES
|
from .const import ERROR_KEYS, ERROR_STATES
|
||||||
from .coordinator import AutomowerDataUpdateCoordinator
|
from .coordinator import AutomowerDataUpdateCoordinator
|
||||||
from .entity import (
|
from .entity import (
|
||||||
AutomowerBaseEntity,
|
AutomowerBaseEntity,
|
||||||
@@ -42,132 +42,6 @@ PARALLEL_UPDATES = 0
|
|||||||
|
|
||||||
ATTR_WORK_AREA_ID_ASSIGNMENT = "work_area_id_assignment"
|
ATTR_WORK_AREA_ID_ASSIGNMENT = "work_area_id_assignment"
|
||||||
|
|
||||||
ERROR_KEYS = [
|
|
||||||
"alarm_mower_in_motion",
|
|
||||||
"alarm_mower_lifted",
|
|
||||||
"alarm_mower_stopped",
|
|
||||||
"alarm_mower_switched_off",
|
|
||||||
"alarm_mower_tilted",
|
|
||||||
"alarm_outside_geofence",
|
|
||||||
"angular_sensor_problem",
|
|
||||||
"battery_problem",
|
|
||||||
"battery_restriction_due_to_ambient_temperature",
|
|
||||||
"can_error",
|
|
||||||
"charging_current_too_high",
|
|
||||||
"charging_station_blocked",
|
|
||||||
"charging_system_problem",
|
|
||||||
"collision_sensor_defect",
|
|
||||||
"collision_sensor_error",
|
|
||||||
"collision_sensor_problem_front",
|
|
||||||
"collision_sensor_problem_rear",
|
|
||||||
"com_board_not_available",
|
|
||||||
"communication_circuit_board_sw_must_be_updated",
|
|
||||||
"complex_working_area",
|
|
||||||
"connection_changed",
|
|
||||||
"connection_not_changed",
|
|
||||||
"connectivity_problem",
|
|
||||||
"connectivity_settings_restored",
|
|
||||||
"cutting_drive_motor_1_defect",
|
|
||||||
"cutting_drive_motor_2_defect",
|
|
||||||
"cutting_drive_motor_3_defect",
|
|
||||||
"cutting_height_blocked",
|
|
||||||
"cutting_height_problem",
|
|
||||||
"cutting_height_problem_curr",
|
|
||||||
"cutting_height_problem_dir",
|
|
||||||
"cutting_height_problem_drive",
|
|
||||||
"cutting_motor_problem",
|
|
||||||
"cutting_stopped_slope_too_steep",
|
|
||||||
"cutting_system_blocked",
|
|
||||||
"cutting_system_imbalance_warning",
|
|
||||||
"cutting_system_major_imbalance",
|
|
||||||
"destination_not_reachable",
|
|
||||||
"difficult_finding_home",
|
|
||||||
"docking_sensor_defect",
|
|
||||||
"electronic_problem",
|
|
||||||
"empty_battery",
|
|
||||||
"folding_cutting_deck_sensor_defect",
|
|
||||||
"folding_sensor_activated",
|
|
||||||
"geofence_problem",
|
|
||||||
"gps_navigation_problem",
|
|
||||||
"guide_1_not_found",
|
|
||||||
"guide_2_not_found",
|
|
||||||
"guide_3_not_found",
|
|
||||||
"guide_calibration_accomplished",
|
|
||||||
"guide_calibration_failed",
|
|
||||||
"high_charging_power_loss",
|
|
||||||
"high_internal_power_loss",
|
|
||||||
"high_internal_temperature",
|
|
||||||
"internal_voltage_error",
|
|
||||||
"invalid_battery_combination_invalid_combination_of_different_battery_types",
|
|
||||||
"invalid_sub_device_combination",
|
|
||||||
"invalid_system_configuration",
|
|
||||||
"left_brush_motor_overloaded",
|
|
||||||
"lift_sensor_defect",
|
|
||||||
"lifted",
|
|
||||||
"limited_cutting_height_range",
|
|
||||||
"loop_sensor_defect",
|
|
||||||
"loop_sensor_problem_front",
|
|
||||||
"loop_sensor_problem_left",
|
|
||||||
"loop_sensor_problem_rear",
|
|
||||||
"loop_sensor_problem_right",
|
|
||||||
"low_battery",
|
|
||||||
"memory_circuit_problem",
|
|
||||||
"mower_lifted",
|
|
||||||
"mower_tilted",
|
|
||||||
"no_accurate_position_from_satellites",
|
|
||||||
"no_confirmed_position",
|
|
||||||
"no_drive",
|
|
||||||
"no_loop_signal",
|
|
||||||
"no_power_in_charging_station",
|
|
||||||
"no_response_from_charger",
|
|
||||||
"outside_working_area",
|
|
||||||
"poor_signal_quality",
|
|
||||||
"reference_station_communication_problem",
|
|
||||||
"right_brush_motor_overloaded",
|
|
||||||
"safety_function_faulty",
|
|
||||||
"settings_restored",
|
|
||||||
"sim_card_locked",
|
|
||||||
"sim_card_not_found",
|
|
||||||
"sim_card_requires_pin",
|
|
||||||
"slipped_mower_has_slipped_situation_not_solved_with_moving_pattern",
|
|
||||||
"slope_too_steep",
|
|
||||||
"sms_could_not_be_sent",
|
|
||||||
"stop_button_problem",
|
|
||||||
"stuck_in_charging_station",
|
|
||||||
"switch_cord_problem",
|
|
||||||
"temporary_battery_problem",
|
|
||||||
"tilt_sensor_problem",
|
|
||||||
"too_high_discharge_current",
|
|
||||||
"too_high_internal_current",
|
|
||||||
"trapped",
|
|
||||||
"ultrasonic_problem",
|
|
||||||
"ultrasonic_sensor_1_defect",
|
|
||||||
"ultrasonic_sensor_2_defect",
|
|
||||||
"ultrasonic_sensor_3_defect",
|
|
||||||
"ultrasonic_sensor_4_defect",
|
|
||||||
"unexpected_cutting_height_adj",
|
|
||||||
"unexpected_error",
|
|
||||||
"upside_down",
|
|
||||||
"weak_gps_signal",
|
|
||||||
"wheel_drive_problem_left",
|
|
||||||
"wheel_drive_problem_rear_left",
|
|
||||||
"wheel_drive_problem_rear_right",
|
|
||||||
"wheel_drive_problem_right",
|
|
||||||
"wheel_motor_blocked_left",
|
|
||||||
"wheel_motor_blocked_rear_left",
|
|
||||||
"wheel_motor_blocked_rear_right",
|
|
||||||
"wheel_motor_blocked_right",
|
|
||||||
"wheel_motor_overloaded_left",
|
|
||||||
"wheel_motor_overloaded_rear_left",
|
|
||||||
"wheel_motor_overloaded_rear_right",
|
|
||||||
"wheel_motor_overloaded_right",
|
|
||||||
"work_area_not_valid",
|
|
||||||
"wrong_loop_signal",
|
|
||||||
"wrong_pin_code",
|
|
||||||
"zone_generator_problem",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
ERROR_KEY_LIST = sorted(
|
ERROR_KEY_LIST = sorted(
|
||||||
set(ERROR_KEYS) | {state.lower() for state in ERROR_STATES} | {"no_error"}
|
set(ERROR_KEYS) | {state.lower() for state in ERROR_STATES} | {"no_error"}
|
||||||
)
|
)
|
||||||
|
@@ -58,6 +58,158 @@
|
|||||||
"name": "Reset cutting blade usage time"
|
"name": "Reset cutting blade usage time"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"event": {
|
||||||
|
"message": {
|
||||||
|
"name": "Message",
|
||||||
|
"state_attributes": {
|
||||||
|
"event_type": {
|
||||||
|
"state": {
|
||||||
|
"alarm_mower_in_motion": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_mower_in_motion%]",
|
||||||
|
"alarm_mower_lifted": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_mower_lifted%]",
|
||||||
|
"alarm_mower_stopped": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_mower_stopped%]",
|
||||||
|
"alarm_mower_switched_off": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_mower_switched_off%]",
|
||||||
|
"alarm_mower_tilted": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_mower_tilted%]",
|
||||||
|
"alarm_outside_geofence": "[%key:component::husqvarna_automower::entity::sensor::error::state::alarm_outside_geofence%]",
|
||||||
|
"angular_sensor_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::angular_sensor_problem%]",
|
||||||
|
"battery_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::battery_problem%]",
|
||||||
|
"battery_restriction_due_to_ambient_temperature": "[%key:component::husqvarna_automower::entity::sensor::error::state::battery_restriction_due_to_ambient_temperature%]",
|
||||||
|
"can_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::can_error%]",
|
||||||
|
"charging_current_too_high": "[%key:component::husqvarna_automower::entity::sensor::error::state::charging_current_too_high%]",
|
||||||
|
"charging_station_blocked": "[%key:component::husqvarna_automower::entity::sensor::error::state::charging_station_blocked%]",
|
||||||
|
"charging_system_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::charging_system_problem%]",
|
||||||
|
"collision_sensor_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::collision_sensor_defect%]",
|
||||||
|
"collision_sensor_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::collision_sensor_error%]",
|
||||||
|
"collision_sensor_problem_front": "[%key:component::husqvarna_automower::entity::sensor::error::state::collision_sensor_problem_front%]",
|
||||||
|
"collision_sensor_problem_rear": "[%key:component::husqvarna_automower::entity::sensor::error::state::collision_sensor_problem_rear%]",
|
||||||
|
"com_board_not_available": "[%key:component::husqvarna_automower::entity::sensor::error::state::com_board_not_available%]",
|
||||||
|
"communication_circuit_board_sw_must_be_updated": "[%key:component::husqvarna_automower::entity::sensor::error::state::communication_circuit_board_sw_must_be_updated%]",
|
||||||
|
"complex_working_area": "[%key:component::husqvarna_automower::entity::sensor::error::state::complex_working_area%]",
|
||||||
|
"connection_changed": "[%key:component::husqvarna_automower::entity::sensor::error::state::connection_changed%]",
|
||||||
|
"connection_not_changed": "[%key:component::husqvarna_automower::entity::sensor::error::state::connection_not_changed%]",
|
||||||
|
"connectivity_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::connectivity_problem%]",
|
||||||
|
"connectivity_settings_restored": "[%key:component::husqvarna_automower::entity::sensor::error::state::connectivity_settings_restored%]",
|
||||||
|
"cutting_drive_motor_1_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_drive_motor_1_defect%]",
|
||||||
|
"cutting_drive_motor_2_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_drive_motor_2_defect%]",
|
||||||
|
"cutting_drive_motor_3_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_drive_motor_3_defect%]",
|
||||||
|
"cutting_height_blocked": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_height_blocked%]",
|
||||||
|
"cutting_height_problem_curr": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_height_problem_curr%]",
|
||||||
|
"cutting_height_problem_dir": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_height_problem_dir%]",
|
||||||
|
"cutting_height_problem_drive": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_height_problem_drive%]",
|
||||||
|
"cutting_height_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_height_problem%]",
|
||||||
|
"cutting_motor_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_motor_problem%]",
|
||||||
|
"cutting_stopped_slope_too_steep": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_stopped_slope_too_steep%]",
|
||||||
|
"cutting_system_blocked": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_system_blocked%]",
|
||||||
|
"cutting_system_imbalance_warning": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_system_imbalance_warning%]",
|
||||||
|
"cutting_system_major_imbalance": "[%key:component::husqvarna_automower::entity::sensor::error::state::cutting_system_major_imbalance%]",
|
||||||
|
"destination_not_reachable": "[%key:component::husqvarna_automower::entity::sensor::error::state::destination_not_reachable%]",
|
||||||
|
"difficult_finding_home": "[%key:component::husqvarna_automower::entity::sensor::error::state::difficult_finding_home%]",
|
||||||
|
"docking_sensor_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::docking_sensor_defect%]",
|
||||||
|
"electronic_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::electronic_problem%]",
|
||||||
|
"empty_battery": "[%key:component::husqvarna_automower::entity::sensor::error::state::empty_battery%]",
|
||||||
|
"error_at_power_up": "[%key:component::husqvarna_automower::entity::sensor::error::state::error_at_power_up%]",
|
||||||
|
"error": "[%key:common::state::error%]",
|
||||||
|
"fatal_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::fatal_error%]",
|
||||||
|
"folding_cutting_deck_sensor_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::folding_cutting_deck_sensor_defect%]",
|
||||||
|
"folding_sensor_activated": "[%key:component::husqvarna_automower::entity::sensor::error::state::folding_sensor_activated%]",
|
||||||
|
"geofence_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::geofence_problem%]",
|
||||||
|
"gps_navigation_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::gps_navigation_problem%]",
|
||||||
|
"guide_1_not_found": "[%key:component::husqvarna_automower::entity::sensor::error::state::guide_1_not_found%]",
|
||||||
|
"guide_2_not_found": "[%key:component::husqvarna_automower::entity::sensor::error::state::guide_2_not_found%]",
|
||||||
|
"guide_3_not_found": "[%key:component::husqvarna_automower::entity::sensor::error::state::guide_3_not_found%]",
|
||||||
|
"guide_calibration_accomplished": "[%key:component::husqvarna_automower::entity::sensor::error::state::guide_calibration_accomplished%]",
|
||||||
|
"guide_calibration_failed": "[%key:component::husqvarna_automower::entity::sensor::error::state::guide_calibration_failed%]",
|
||||||
|
"high_charging_power_loss": "[%key:component::husqvarna_automower::entity::sensor::error::state::high_charging_power_loss%]",
|
||||||
|
"high_internal_power_loss": "[%key:component::husqvarna_automower::entity::sensor::error::state::high_internal_power_loss%]",
|
||||||
|
"high_internal_temperature": "[%key:component::husqvarna_automower::entity::sensor::error::state::high_internal_temperature%]",
|
||||||
|
"internal_voltage_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::internal_voltage_error%]",
|
||||||
|
"invalid_battery_combination_invalid_combination_of_different_battery_types": "[%key:component::husqvarna_automower::entity::sensor::error::state::invalid_battery_combination_invalid_combination_of_different_battery_types%]",
|
||||||
|
"invalid_sub_device_combination": "[%key:component::husqvarna_automower::entity::sensor::error::state::invalid_sub_device_combination%]",
|
||||||
|
"invalid_system_configuration": "[%key:component::husqvarna_automower::entity::sensor::error::state::invalid_system_configuration%]",
|
||||||
|
"left_brush_motor_overloaded": "[%key:component::husqvarna_automower::entity::sensor::error::state::left_brush_motor_overloaded%]",
|
||||||
|
"lift_sensor_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::lift_sensor_defect%]",
|
||||||
|
"lifted": "[%key:component::husqvarna_automower::entity::sensor::error::state::lifted%]",
|
||||||
|
"limited_cutting_height_range": "[%key:component::husqvarna_automower::entity::sensor::error::state::limited_cutting_height_range%]",
|
||||||
|
"loop_sensor_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::loop_sensor_defect%]",
|
||||||
|
"loop_sensor_problem_front": "[%key:component::husqvarna_automower::entity::sensor::error::state::loop_sensor_problem_front%]",
|
||||||
|
"loop_sensor_problem_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::loop_sensor_problem_left%]",
|
||||||
|
"loop_sensor_problem_rear": "[%key:component::husqvarna_automower::entity::sensor::error::state::loop_sensor_problem_rear%]",
|
||||||
|
"loop_sensor_problem_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::loop_sensor_problem_right%]",
|
||||||
|
"low_battery": "[%key:component::husqvarna_automower::entity::sensor::error::state::low_battery%]",
|
||||||
|
"memory_circuit_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::memory_circuit_problem%]",
|
||||||
|
"mower_lifted": "[%key:component::husqvarna_automower::entity::sensor::error::state::mower_lifted%]",
|
||||||
|
"mower_tilted": "[%key:component::husqvarna_automower::entity::sensor::error::state::mower_tilted%]",
|
||||||
|
"no_accurate_position_from_satellites": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_accurate_position_from_satellites%]",
|
||||||
|
"no_confirmed_position": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_confirmed_position%]",
|
||||||
|
"no_drive": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_drive%]",
|
||||||
|
"no_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_error%]",
|
||||||
|
"no_loop_signal": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_loop_signal%]",
|
||||||
|
"no_power_in_charging_station": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_power_in_charging_station%]",
|
||||||
|
"no_response_from_charger": "[%key:component::husqvarna_automower::entity::sensor::error::state::no_response_from_charger%]",
|
||||||
|
"off": "[%key:common::state::off%]",
|
||||||
|
"outside_working_area": "[%key:component::husqvarna_automower::entity::sensor::error::state::outside_working_area%]",
|
||||||
|
"poor_signal_quality": "[%key:component::husqvarna_automower::entity::sensor::error::state::poor_signal_quality%]",
|
||||||
|
"reference_station_communication_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::reference_station_communication_problem%]",
|
||||||
|
"right_brush_motor_overloaded": "[%key:component::husqvarna_automower::entity::sensor::error::state::right_brush_motor_overloaded%]",
|
||||||
|
"safety_function_faulty": "[%key:component::husqvarna_automower::entity::sensor::error::state::safety_function_faulty%]",
|
||||||
|
"settings_restored": "[%key:component::husqvarna_automower::entity::sensor::error::state::settings_restored%]",
|
||||||
|
"sim_card_locked": "[%key:component::husqvarna_automower::entity::sensor::error::state::sim_card_locked%]",
|
||||||
|
"sim_card_not_found": "[%key:component::husqvarna_automower::entity::sensor::error::state::sim_card_not_found%]",
|
||||||
|
"sim_card_requires_pin": "[%key:component::husqvarna_automower::entity::sensor::error::state::sim_card_requires_pin%]",
|
||||||
|
"slipped_mower_has_slipped_situation_not_solved_with_moving_pattern": "[%key:component::husqvarna_automower::entity::sensor::error::state::slipped_mower_has_slipped_situation_not_solved_with_moving_pattern%]",
|
||||||
|
"slope_too_steep": "[%key:component::husqvarna_automower::entity::sensor::error::state::slope_too_steep%]",
|
||||||
|
"sms_could_not_be_sent": "[%key:component::husqvarna_automower::entity::sensor::error::state::sms_could_not_be_sent%]",
|
||||||
|
"stop_button_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::stop_button_problem%]",
|
||||||
|
"stopped": "[%key:common::state::stopped%]",
|
||||||
|
"stuck_in_charging_station": "[%key:component::husqvarna_automower::entity::sensor::error::state::stuck_in_charging_station%]",
|
||||||
|
"switch_cord_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::switch_cord_problem%]",
|
||||||
|
"temporary_battery_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::temporary_battery_problem%]",
|
||||||
|
"tilt_sensor_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::tilt_sensor_problem%]",
|
||||||
|
"too_high_discharge_current": "[%key:component::husqvarna_automower::entity::sensor::error::state::too_high_discharge_current%]",
|
||||||
|
"too_high_internal_current": "[%key:component::husqvarna_automower::entity::sensor::error::state::too_high_internal_current%]",
|
||||||
|
"trapped": "[%key:component::husqvarna_automower::entity::sensor::error::state::trapped%]",
|
||||||
|
"ultrasonic_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::ultrasonic_problem%]",
|
||||||
|
"ultrasonic_sensor_1_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::ultrasonic_sensor_1_defect%]",
|
||||||
|
"ultrasonic_sensor_2_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::ultrasonic_sensor_2_defect%]",
|
||||||
|
"ultrasonic_sensor_3_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::ultrasonic_sensor_3_defect%]",
|
||||||
|
"ultrasonic_sensor_4_defect": "[%key:component::husqvarna_automower::entity::sensor::error::state::ultrasonic_sensor_4_defect%]",
|
||||||
|
"unexpected_cutting_height_adj": "[%key:component::husqvarna_automower::entity::sensor::error::state::unexpected_cutting_height_adj%]",
|
||||||
|
"unexpected_error": "[%key:component::husqvarna_automower::entity::sensor::error::state::unexpected_error%]",
|
||||||
|
"upside_down": "[%key:component::husqvarna_automower::entity::sensor::error::state::upside_down%]",
|
||||||
|
"wait_power_up": "[%key:component::husqvarna_automower::entity::sensor::error::state::wait_power_up%]",
|
||||||
|
"wait_updating": "[%key:component::husqvarna_automower::entity::sensor::error::state::wait_updating%]",
|
||||||
|
"weak_gps_signal": "[%key:component::husqvarna_automower::entity::sensor::error::state::weak_gps_signal%]",
|
||||||
|
"wheel_drive_problem_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_drive_problem_left%]",
|
||||||
|
"wheel_drive_problem_rear_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_drive_problem_rear_left%]",
|
||||||
|
"wheel_drive_problem_rear_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_drive_problem_rear_right%]",
|
||||||
|
"wheel_drive_problem_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_drive_problem_right%]",
|
||||||
|
"wheel_motor_blocked_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_blocked_left%]",
|
||||||
|
"wheel_motor_blocked_rear_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_blocked_rear_left%]",
|
||||||
|
"wheel_motor_blocked_rear_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_blocked_rear_right%]",
|
||||||
|
"wheel_motor_blocked_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_blocked_right%]",
|
||||||
|
"wheel_motor_overloaded_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_overloaded_left%]",
|
||||||
|
"wheel_motor_overloaded_rear_left": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_overloaded_rear_left%]",
|
||||||
|
"wheel_motor_overloaded_rear_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_overloaded_rear_right%]",
|
||||||
|
"wheel_motor_overloaded_right": "[%key:component::husqvarna_automower::entity::sensor::error::state::wheel_motor_overloaded_right%]",
|
||||||
|
"work_area_not_valid": "[%key:component::husqvarna_automower::entity::sensor::error::state::work_area_not_valid%]",
|
||||||
|
"wrong_loop_signal": "[%key:component::husqvarna_automower::entity::sensor::error::state::wrong_loop_signal%]",
|
||||||
|
"wrong_pin_code": "[%key:component::husqvarna_automower::entity::sensor::error::state::wrong_pin_code%]",
|
||||||
|
"zone_generator_problem": "[%key:component::husqvarna_automower::entity::sensor::error::state::zone_generator_problem%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"severity": {
|
||||||
|
"state": {
|
||||||
|
"fatal": "Fatal",
|
||||||
|
"error": "[%key:common::state::error%]",
|
||||||
|
"warning": "Warning",
|
||||||
|
"info": "Info",
|
||||||
|
"debug": "Debug",
|
||||||
|
"sw": "Software",
|
||||||
|
"unknown": "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"cutting_height": {
|
"cutting_height": {
|
||||||
"name": "Cutting height"
|
"name": "Cutting height"
|
||||||
|
303
tests/components/husqvarna_automower/snapshots/test_event.ambr
Normal file
303
tests/components/husqvarna_automower/snapshots/test_event.ambr
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_event_snapshot[event.test_mower_1_message-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'event_types': list([
|
||||||
|
'alarm_mower_in_motion',
|
||||||
|
'alarm_mower_lifted',
|
||||||
|
'alarm_mower_stopped',
|
||||||
|
'alarm_mower_switched_off',
|
||||||
|
'alarm_mower_tilted',
|
||||||
|
'alarm_outside_geofence',
|
||||||
|
'angular_sensor_problem',
|
||||||
|
'battery_problem',
|
||||||
|
'battery_restriction_due_to_ambient_temperature',
|
||||||
|
'can_error',
|
||||||
|
'charging_current_too_high',
|
||||||
|
'charging_station_blocked',
|
||||||
|
'charging_system_problem',
|
||||||
|
'collision_sensor_defect',
|
||||||
|
'collision_sensor_error',
|
||||||
|
'collision_sensor_problem_front',
|
||||||
|
'collision_sensor_problem_rear',
|
||||||
|
'com_board_not_available',
|
||||||
|
'communication_circuit_board_sw_must_be_updated',
|
||||||
|
'complex_working_area',
|
||||||
|
'connection_changed',
|
||||||
|
'connection_not_changed',
|
||||||
|
'connectivity_problem',
|
||||||
|
'connectivity_settings_restored',
|
||||||
|
'cutting_drive_motor_1_defect',
|
||||||
|
'cutting_drive_motor_2_defect',
|
||||||
|
'cutting_drive_motor_3_defect',
|
||||||
|
'cutting_height_blocked',
|
||||||
|
'cutting_height_problem',
|
||||||
|
'cutting_height_problem_curr',
|
||||||
|
'cutting_height_problem_dir',
|
||||||
|
'cutting_height_problem_drive',
|
||||||
|
'cutting_motor_problem',
|
||||||
|
'cutting_stopped_slope_too_steep',
|
||||||
|
'cutting_system_blocked',
|
||||||
|
'cutting_system_imbalance_warning',
|
||||||
|
'cutting_system_major_imbalance',
|
||||||
|
'destination_not_reachable',
|
||||||
|
'difficult_finding_home',
|
||||||
|
'docking_sensor_defect',
|
||||||
|
'electronic_problem',
|
||||||
|
'empty_battery',
|
||||||
|
'folding_cutting_deck_sensor_defect',
|
||||||
|
'folding_sensor_activated',
|
||||||
|
'geofence_problem',
|
||||||
|
'gps_navigation_problem',
|
||||||
|
'guide_1_not_found',
|
||||||
|
'guide_2_not_found',
|
||||||
|
'guide_3_not_found',
|
||||||
|
'guide_calibration_accomplished',
|
||||||
|
'guide_calibration_failed',
|
||||||
|
'high_charging_power_loss',
|
||||||
|
'high_internal_power_loss',
|
||||||
|
'high_internal_temperature',
|
||||||
|
'internal_voltage_error',
|
||||||
|
'invalid_battery_combination_invalid_combination_of_different_battery_types',
|
||||||
|
'invalid_sub_device_combination',
|
||||||
|
'invalid_system_configuration',
|
||||||
|
'left_brush_motor_overloaded',
|
||||||
|
'lift_sensor_defect',
|
||||||
|
'lifted',
|
||||||
|
'limited_cutting_height_range',
|
||||||
|
'loop_sensor_defect',
|
||||||
|
'loop_sensor_problem_front',
|
||||||
|
'loop_sensor_problem_left',
|
||||||
|
'loop_sensor_problem_rear',
|
||||||
|
'loop_sensor_problem_right',
|
||||||
|
'low_battery',
|
||||||
|
'memory_circuit_problem',
|
||||||
|
'mower_lifted',
|
||||||
|
'mower_tilted',
|
||||||
|
'no_accurate_position_from_satellites',
|
||||||
|
'no_confirmed_position',
|
||||||
|
'no_drive',
|
||||||
|
'no_loop_signal',
|
||||||
|
'no_power_in_charging_station',
|
||||||
|
'no_response_from_charger',
|
||||||
|
'outside_working_area',
|
||||||
|
'poor_signal_quality',
|
||||||
|
'reference_station_communication_problem',
|
||||||
|
'right_brush_motor_overloaded',
|
||||||
|
'safety_function_faulty',
|
||||||
|
'settings_restored',
|
||||||
|
'sim_card_locked',
|
||||||
|
'sim_card_not_found',
|
||||||
|
'sim_card_requires_pin',
|
||||||
|
'slipped_mower_has_slipped_situation_not_solved_with_moving_pattern',
|
||||||
|
'slope_too_steep',
|
||||||
|
'sms_could_not_be_sent',
|
||||||
|
'stop_button_problem',
|
||||||
|
'stuck_in_charging_station',
|
||||||
|
'switch_cord_problem',
|
||||||
|
'temporary_battery_problem',
|
||||||
|
'tilt_sensor_problem',
|
||||||
|
'too_high_discharge_current',
|
||||||
|
'too_high_internal_current',
|
||||||
|
'trapped',
|
||||||
|
'ultrasonic_problem',
|
||||||
|
'ultrasonic_sensor_1_defect',
|
||||||
|
'ultrasonic_sensor_2_defect',
|
||||||
|
'ultrasonic_sensor_3_defect',
|
||||||
|
'ultrasonic_sensor_4_defect',
|
||||||
|
'unexpected_cutting_height_adj',
|
||||||
|
'unexpected_error',
|
||||||
|
'upside_down',
|
||||||
|
'weak_gps_signal',
|
||||||
|
'wheel_drive_problem_left',
|
||||||
|
'wheel_drive_problem_rear_left',
|
||||||
|
'wheel_drive_problem_rear_right',
|
||||||
|
'wheel_drive_problem_right',
|
||||||
|
'wheel_motor_blocked_left',
|
||||||
|
'wheel_motor_blocked_rear_left',
|
||||||
|
'wheel_motor_blocked_rear_right',
|
||||||
|
'wheel_motor_blocked_right',
|
||||||
|
'wheel_motor_overloaded_left',
|
||||||
|
'wheel_motor_overloaded_rear_left',
|
||||||
|
'wheel_motor_overloaded_rear_right',
|
||||||
|
'wheel_motor_overloaded_right',
|
||||||
|
'work_area_not_valid',
|
||||||
|
'wrong_loop_signal',
|
||||||
|
'wrong_pin_code',
|
||||||
|
'zone_generator_problem',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'event',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'event.test_mower_1_message',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Message',
|
||||||
|
'platform': 'husqvarna_automower',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'suggested_object_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'message',
|
||||||
|
'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_message',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_event_snapshot[event.test_mower_1_message-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'date_time': HAFakeDatetime(2025, 7, 13, 15, 30, tzinfo=datetime.timezone.utc),
|
||||||
|
'event_type': 'wheel_motor_overloaded_rear_left',
|
||||||
|
'event_types': list([
|
||||||
|
'alarm_mower_in_motion',
|
||||||
|
'alarm_mower_lifted',
|
||||||
|
'alarm_mower_stopped',
|
||||||
|
'alarm_mower_switched_off',
|
||||||
|
'alarm_mower_tilted',
|
||||||
|
'alarm_outside_geofence',
|
||||||
|
'angular_sensor_problem',
|
||||||
|
'battery_problem',
|
||||||
|
'battery_restriction_due_to_ambient_temperature',
|
||||||
|
'can_error',
|
||||||
|
'charging_current_too_high',
|
||||||
|
'charging_station_blocked',
|
||||||
|
'charging_system_problem',
|
||||||
|
'collision_sensor_defect',
|
||||||
|
'collision_sensor_error',
|
||||||
|
'collision_sensor_problem_front',
|
||||||
|
'collision_sensor_problem_rear',
|
||||||
|
'com_board_not_available',
|
||||||
|
'communication_circuit_board_sw_must_be_updated',
|
||||||
|
'complex_working_area',
|
||||||
|
'connection_changed',
|
||||||
|
'connection_not_changed',
|
||||||
|
'connectivity_problem',
|
||||||
|
'connectivity_settings_restored',
|
||||||
|
'cutting_drive_motor_1_defect',
|
||||||
|
'cutting_drive_motor_2_defect',
|
||||||
|
'cutting_drive_motor_3_defect',
|
||||||
|
'cutting_height_blocked',
|
||||||
|
'cutting_height_problem',
|
||||||
|
'cutting_height_problem_curr',
|
||||||
|
'cutting_height_problem_dir',
|
||||||
|
'cutting_height_problem_drive',
|
||||||
|
'cutting_motor_problem',
|
||||||
|
'cutting_stopped_slope_too_steep',
|
||||||
|
'cutting_system_blocked',
|
||||||
|
'cutting_system_imbalance_warning',
|
||||||
|
'cutting_system_major_imbalance',
|
||||||
|
'destination_not_reachable',
|
||||||
|
'difficult_finding_home',
|
||||||
|
'docking_sensor_defect',
|
||||||
|
'electronic_problem',
|
||||||
|
'empty_battery',
|
||||||
|
'folding_cutting_deck_sensor_defect',
|
||||||
|
'folding_sensor_activated',
|
||||||
|
'geofence_problem',
|
||||||
|
'gps_navigation_problem',
|
||||||
|
'guide_1_not_found',
|
||||||
|
'guide_2_not_found',
|
||||||
|
'guide_3_not_found',
|
||||||
|
'guide_calibration_accomplished',
|
||||||
|
'guide_calibration_failed',
|
||||||
|
'high_charging_power_loss',
|
||||||
|
'high_internal_power_loss',
|
||||||
|
'high_internal_temperature',
|
||||||
|
'internal_voltage_error',
|
||||||
|
'invalid_battery_combination_invalid_combination_of_different_battery_types',
|
||||||
|
'invalid_sub_device_combination',
|
||||||
|
'invalid_system_configuration',
|
||||||
|
'left_brush_motor_overloaded',
|
||||||
|
'lift_sensor_defect',
|
||||||
|
'lifted',
|
||||||
|
'limited_cutting_height_range',
|
||||||
|
'loop_sensor_defect',
|
||||||
|
'loop_sensor_problem_front',
|
||||||
|
'loop_sensor_problem_left',
|
||||||
|
'loop_sensor_problem_rear',
|
||||||
|
'loop_sensor_problem_right',
|
||||||
|
'low_battery',
|
||||||
|
'memory_circuit_problem',
|
||||||
|
'mower_lifted',
|
||||||
|
'mower_tilted',
|
||||||
|
'no_accurate_position_from_satellites',
|
||||||
|
'no_confirmed_position',
|
||||||
|
'no_drive',
|
||||||
|
'no_loop_signal',
|
||||||
|
'no_power_in_charging_station',
|
||||||
|
'no_response_from_charger',
|
||||||
|
'outside_working_area',
|
||||||
|
'poor_signal_quality',
|
||||||
|
'reference_station_communication_problem',
|
||||||
|
'right_brush_motor_overloaded',
|
||||||
|
'safety_function_faulty',
|
||||||
|
'settings_restored',
|
||||||
|
'sim_card_locked',
|
||||||
|
'sim_card_not_found',
|
||||||
|
'sim_card_requires_pin',
|
||||||
|
'slipped_mower_has_slipped_situation_not_solved_with_moving_pattern',
|
||||||
|
'slope_too_steep',
|
||||||
|
'sms_could_not_be_sent',
|
||||||
|
'stop_button_problem',
|
||||||
|
'stuck_in_charging_station',
|
||||||
|
'switch_cord_problem',
|
||||||
|
'temporary_battery_problem',
|
||||||
|
'tilt_sensor_problem',
|
||||||
|
'too_high_discharge_current',
|
||||||
|
'too_high_internal_current',
|
||||||
|
'trapped',
|
||||||
|
'ultrasonic_problem',
|
||||||
|
'ultrasonic_sensor_1_defect',
|
||||||
|
'ultrasonic_sensor_2_defect',
|
||||||
|
'ultrasonic_sensor_3_defect',
|
||||||
|
'ultrasonic_sensor_4_defect',
|
||||||
|
'unexpected_cutting_height_adj',
|
||||||
|
'unexpected_error',
|
||||||
|
'upside_down',
|
||||||
|
'weak_gps_signal',
|
||||||
|
'wheel_drive_problem_left',
|
||||||
|
'wheel_drive_problem_rear_left',
|
||||||
|
'wheel_drive_problem_rear_right',
|
||||||
|
'wheel_drive_problem_right',
|
||||||
|
'wheel_motor_blocked_left',
|
||||||
|
'wheel_motor_blocked_rear_left',
|
||||||
|
'wheel_motor_blocked_rear_right',
|
||||||
|
'wheel_motor_blocked_right',
|
||||||
|
'wheel_motor_overloaded_left',
|
||||||
|
'wheel_motor_overloaded_rear_left',
|
||||||
|
'wheel_motor_overloaded_rear_right',
|
||||||
|
'wheel_motor_overloaded_right',
|
||||||
|
'work_area_not_valid',
|
||||||
|
'wrong_loop_signal',
|
||||||
|
'wrong_pin_code',
|
||||||
|
'zone_generator_problem',
|
||||||
|
]),
|
||||||
|
'friendly_name': 'Test Mower 1 Message',
|
||||||
|
'latitude': 49.0,
|
||||||
|
'longitude': 10.0,
|
||||||
|
'severity': <Severity.ERROR: 'error'>,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'event.test_mower_1_message',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '2023-06-05T12:00:00.000+00:00',
|
||||||
|
})
|
||||||
|
# ---
|
206
tests/components/husqvarna_automower/test_event.py
Normal file
206
tests/components/husqvarna_automower/test_event.py
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
"""Tests for init module."""
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from copy import deepcopy
|
||||||
|
from datetime import UTC, datetime
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
from aioautomower.model import MowerAttributes, SingleMessageData
|
||||||
|
from aioautomower.model.model_message import Message, Severity, SingleMessageAttributes
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
|
import pytest
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.event import ATTR_EVENT_TYPE
|
||||||
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import Platform
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
from .const import TEST_MOWER_ID
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime(2023, 6, 5, 12))
|
||||||
|
async def test_event(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: EntityRegistry,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
values: dict[str, MowerAttributes],
|
||||||
|
) -> None:
|
||||||
|
"""Test that a new message arriving over the websocket creates and updates the sensor."""
|
||||||
|
callbacks: list[Callable[[SingleMessageData], None]] = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def fake_register_websocket_response(
|
||||||
|
cb: Callable[[SingleMessageData], None],
|
||||||
|
) -> None:
|
||||||
|
callbacks.append(cb)
|
||||||
|
|
||||||
|
mock_automower_client.register_single_message_callback.side_effect = (
|
||||||
|
fake_register_websocket_response
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up integration
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Ensure callback was registered for the test mower
|
||||||
|
assert mock_automower_client.register_single_message_callback.called
|
||||||
|
|
||||||
|
# Check initial state (event entity not available yet)
|
||||||
|
state = hass.states.get("event.test_mower_1_message")
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
# Simulate a new message for this mower and check entity creation
|
||||||
|
message = SingleMessageData(
|
||||||
|
type="messages",
|
||||||
|
id=TEST_MOWER_ID,
|
||||||
|
attributes=SingleMessageAttributes(
|
||||||
|
message=Message(
|
||||||
|
time=datetime(2025, 7, 13, 15, 30, tzinfo=UTC),
|
||||||
|
code="wheel_motor_overloaded_rear_left",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
latitude=49.0,
|
||||||
|
longitude=10.0,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for cb in callbacks:
|
||||||
|
cb(message)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("event.test_mower_1_message")
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes[ATTR_EVENT_TYPE] == "wheel_motor_overloaded_rear_left"
|
||||||
|
|
||||||
|
# Reload the config entry to ensure the entity is created again
|
||||||
|
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||||
|
state = hass.states.get("event.test_mower_1_message")
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes[ATTR_EVENT_TYPE] == "wheel_motor_overloaded_rear_left"
|
||||||
|
|
||||||
|
# Check updating event with a new message
|
||||||
|
message = SingleMessageData(
|
||||||
|
type="messages",
|
||||||
|
id=TEST_MOWER_ID,
|
||||||
|
attributes=SingleMessageAttributes(
|
||||||
|
message=Message(
|
||||||
|
time=datetime(2025, 7, 13, 16, 00, tzinfo=UTC),
|
||||||
|
code="alarm_mower_lifted",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
latitude=48.0,
|
||||||
|
longitude=11.0,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for cb in callbacks:
|
||||||
|
cb(message)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("event.test_mower_1_message")
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes[ATTR_EVENT_TYPE] == "alarm_mower_lifted"
|
||||||
|
|
||||||
|
# Check message for another mower, creates an new entity and dont
|
||||||
|
# change the state of the first entity
|
||||||
|
message = SingleMessageData(
|
||||||
|
type="messages",
|
||||||
|
id="1234",
|
||||||
|
attributes=SingleMessageAttributes(
|
||||||
|
message=Message(
|
||||||
|
time=datetime(2025, 7, 13, 16, 00, tzinfo=UTC),
|
||||||
|
code="battery_problem",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
latitude=48.0,
|
||||||
|
longitude=11.0,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for cb in callbacks:
|
||||||
|
cb(message)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
entry = entity_registry.async_get("event.test_mower_1_message")
|
||||||
|
assert entry is not None
|
||||||
|
assert state.attributes[ATTR_EVENT_TYPE] == "alarm_mower_lifted"
|
||||||
|
state = hass.states.get("event.test_mower_2_message")
|
||||||
|
assert state is not None
|
||||||
|
assert state.attributes[ATTR_EVENT_TYPE] == "battery_problem"
|
||||||
|
|
||||||
|
# Check event entity is removed, when the mower is removed
|
||||||
|
values_copy = deepcopy(values)
|
||||||
|
values_copy.pop("1234")
|
||||||
|
mock_automower_client.get_status.return_value = values_copy
|
||||||
|
freezer.tick(SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("event.test_mower_2_message")
|
||||||
|
assert state is None
|
||||||
|
entry = entity_registry.async_get("event.test_mower_2_message")
|
||||||
|
assert entry is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime(2023, 6, 5, 12))
|
||||||
|
async def test_event_snapshot(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test that a new message arriving over the websocket updates the sensor."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.husqvarna_automower.PLATFORMS",
|
||||||
|
[Platform.EVENT],
|
||||||
|
):
|
||||||
|
callbacks: list[Callable[[SingleMessageData], None]] = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def fake_register_websocket_response(
|
||||||
|
cb: Callable[[SingleMessageData], None],
|
||||||
|
) -> None:
|
||||||
|
callbacks.append(cb)
|
||||||
|
|
||||||
|
mock_automower_client.register_single_message_callback.side_effect = (
|
||||||
|
fake_register_websocket_response
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up integration
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Ensure callback was registered for the test mower
|
||||||
|
assert mock_automower_client.register_single_message_callback.called
|
||||||
|
|
||||||
|
# Simulate a new message for this mower
|
||||||
|
message = SingleMessageData(
|
||||||
|
type="messages",
|
||||||
|
id=TEST_MOWER_ID,
|
||||||
|
attributes=SingleMessageAttributes(
|
||||||
|
message=Message(
|
||||||
|
time=datetime(2025, 7, 13, 15, 30, tzinfo=UTC),
|
||||||
|
code="wheel_motor_overloaded_rear_left",
|
||||||
|
severity=Severity.ERROR,
|
||||||
|
latitude=49.0,
|
||||||
|
longitude=10.0,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for cb in callbacks:
|
||||||
|
cb(message)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await snapshot_platform(
|
||||||
|
hass, entity_registry, snapshot, mock_config_entry.entry_id
|
||||||
|
)
|
Reference in New Issue
Block a user