mirror of
https://github.com/home-assistant/core.git
synced 2026-02-27 20:41:44 +01:00
Compare commits
1 Commits
dev
...
epenet/202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
662554ec46 |
4
CODEOWNERS
generated
4
CODEOWNERS
generated
@@ -1901,8 +1901,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/withings/ @joostlek
|
||||
/homeassistant/components/wiz/ @sbidy @arturpragacz
|
||||
/tests/components/wiz/ @sbidy @arturpragacz
|
||||
/homeassistant/components/wled/ @frenck @mik-laj
|
||||
/tests/components/wled/ @frenck @mik-laj
|
||||
/homeassistant/components/wled/ @frenck
|
||||
/tests/components/wled/ @frenck
|
||||
/homeassistant/components/wmspro/ @mback2k
|
||||
/tests/components/wmspro/ @mback2k
|
||||
/homeassistant/components/wolflink/ @adamkrol93 @mtielen
|
||||
|
||||
@@ -13,7 +13,6 @@ UID = "uid"
|
||||
BCU_APP = "BCU-APP"
|
||||
WITHOUT_CHARGING_CARD = "without_charging_card"
|
||||
CHARGING_CARD_ID = "charging_card_id"
|
||||
SERVICE_START_CHARGE_SESSION = "start_charge_session"
|
||||
PLUG_AND_CHARGE = "plug_and_charge"
|
||||
VALUE = "value"
|
||||
PERMISSION = "permission"
|
||||
|
||||
@@ -10,7 +10,7 @@ from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
|
||||
from .const import BCU_APP, CHARGING_CARD_ID, DOMAIN, SERVICE_START_CHARGE_SESSION
|
||||
from .const import BCU_APP, CHARGING_CARD_ID, DOMAIN
|
||||
|
||||
SERVICE_START_CHARGE_SESSION_SCHEMA = vol.Schema(
|
||||
{
|
||||
@@ -73,7 +73,7 @@ def async_setup_services(hass: HomeAssistant) -> None:
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
start_charge_session,
|
||||
SERVICE_START_CHARGE_SESSION_SCHEMA,
|
||||
)
|
||||
|
||||
@@ -64,8 +64,6 @@ SENSOR_TYPES: tuple[BSBLanSensorEntityDescription, ...] = (
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
suggested_display_precision=0,
|
||||
entity_registry_enabled_default=False,
|
||||
value_fn=lambda data: (
|
||||
data.sensor.total_energy.value
|
||||
if data.sensor.total_energy is not None
|
||||
|
||||
@@ -31,6 +31,10 @@ ATTR_FRIDAY_SLOTS = "friday_slots"
|
||||
ATTR_SATURDAY_SLOTS = "saturday_slots"
|
||||
ATTR_SUNDAY_SLOTS = "sunday_slots"
|
||||
|
||||
# Service names
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE = "set_hot_water_schedule"
|
||||
SERVICE_SYNC_TIME = "sync_time"
|
||||
|
||||
|
||||
# Schema for a single time slot
|
||||
_SLOT_SCHEMA = vol.Schema(
|
||||
@@ -256,14 +260,14 @@ def async_setup_services(hass: HomeAssistant) -> None:
|
||||
"""Register the BSB-LAN services."""
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
set_hot_water_schedule,
|
||||
schema=SERVICE_SET_HOT_WATER_SCHEDULE_SCHEMA,
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
"sync_time",
|
||||
SERVICE_SYNC_TIME,
|
||||
async_sync_time,
|
||||
schema=SYNC_TIME_SCHEMA,
|
||||
)
|
||||
|
||||
@@ -33,8 +33,6 @@ DUNEHD_PLAYER_SUPPORT: Final[MediaPlayerEntityFeature] = (
|
||||
| MediaPlayerEntityFeature.PLAY
|
||||
| MediaPlayerEntityFeature.PLAY_MEDIA
|
||||
| MediaPlayerEntityFeature.BROWSE_MEDIA
|
||||
| MediaPlayerEntityFeature.VOLUME_STEP
|
||||
| MediaPlayerEntityFeature.VOLUME_MUTE
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -405,13 +405,8 @@ CT_SENSORS = (
|
||||
)
|
||||
for cttype, key in (
|
||||
(CtType.NET_CONSUMPTION, "lifetime_net_consumption"),
|
||||
(CtType.PRODUCTION, "production_ct_energy_delivered"),
|
||||
# Production CT energy_delivered is not used
|
||||
(CtType.STORAGE, "lifetime_battery_discharged"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_energy_delivered"),
|
||||
(CtType.BACKFEED, "backfeed_ct_energy_delivered"),
|
||||
(CtType.LOAD, "load_ct_energy_delivered"),
|
||||
(CtType.EVSE, "evse_ct_energy_delivered"),
|
||||
(CtType.PV3P, "pv3p_ct_energy_delivered"),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -428,13 +423,8 @@ CT_SENSORS = (
|
||||
)
|
||||
for cttype, key in (
|
||||
(CtType.NET_CONSUMPTION, "lifetime_net_production"),
|
||||
(CtType.PRODUCTION, "production_ct_energy_received"),
|
||||
# Production CT energy_received is not used
|
||||
(CtType.STORAGE, "lifetime_battery_charged"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_energy_received"),
|
||||
(CtType.BACKFEED, "backfeed_ct_energy_received"),
|
||||
(CtType.LOAD, "load_ct_energy_received"),
|
||||
(CtType.EVSE, "evse_ct_energy_received"),
|
||||
(CtType.PV3P, "pv3p_ct_energy_received"),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -451,13 +441,8 @@ CT_SENSORS = (
|
||||
)
|
||||
for cttype, key in (
|
||||
(CtType.NET_CONSUMPTION, "net_consumption"),
|
||||
(CtType.PRODUCTION, "production_ct_power"),
|
||||
# Production CT active_power is not used
|
||||
(CtType.STORAGE, "battery_discharge"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_power"),
|
||||
(CtType.BACKFEED, "backfeed_ct_power"),
|
||||
(CtType.LOAD, "load_ct_power"),
|
||||
(CtType.EVSE, "evse_ct_power"),
|
||||
(CtType.PV3P, "pv3p_ct_power"),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -476,11 +461,6 @@ CT_SENSORS = (
|
||||
(CtType.NET_CONSUMPTION, "frequency", "net_ct_frequency"),
|
||||
(CtType.PRODUCTION, "production_ct_frequency", ""),
|
||||
(CtType.STORAGE, "storage_ct_frequency", ""),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_frequency", ""),
|
||||
(CtType.BACKFEED, "backfeed_ct_frequency", ""),
|
||||
(CtType.LOAD, "load_ct_frequency", ""),
|
||||
(CtType.EVSE, "evse_ct_frequency", ""),
|
||||
(CtType.PV3P, "pv3p_ct_frequency", ""),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -500,11 +480,6 @@ CT_SENSORS = (
|
||||
(CtType.NET_CONSUMPTION, "voltage", "net_ct_voltage"),
|
||||
(CtType.PRODUCTION, "production_ct_voltage", ""),
|
||||
(CtType.STORAGE, "storage_voltage", "storage_ct_voltage"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_voltage", ""),
|
||||
(CtType.BACKFEED, "backfeed_ct_voltage", ""),
|
||||
(CtType.LOAD, "load_ct_voltage", ""),
|
||||
(CtType.EVSE, "evse_ct_voltage", ""),
|
||||
(CtType.PV3P, "pv3p_ct_voltage", ""),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -524,11 +499,6 @@ CT_SENSORS = (
|
||||
(CtType.NET_CONSUMPTION, "net_ct_current"),
|
||||
(CtType.PRODUCTION, "production_ct_current"),
|
||||
(CtType.STORAGE, "storage_ct_current"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_current"),
|
||||
(CtType.BACKFEED, "backfeed_ct_current"),
|
||||
(CtType.LOAD, "load_ct_current"),
|
||||
(CtType.EVSE, "evse_ct_current"),
|
||||
(CtType.PV3P, "pv3p_ct_current"),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -546,11 +516,6 @@ CT_SENSORS = (
|
||||
(CtType.NET_CONSUMPTION, "net_ct_powerfactor"),
|
||||
(CtType.PRODUCTION, "production_ct_powerfactor"),
|
||||
(CtType.STORAGE, "storage_ct_powerfactor"),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_powerfactor"),
|
||||
(CtType.BACKFEED, "backfeed_ct_powerfactor"),
|
||||
(CtType.LOAD, "load_ct_powerfactor"),
|
||||
(CtType.EVSE, "evse_ct_powerfactor"),
|
||||
(CtType.PV3P, "pv3p_ct_powerfactor"),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -572,11 +537,6 @@ CT_SENSORS = (
|
||||
),
|
||||
(CtType.PRODUCTION, "production_ct_metering_status", ""),
|
||||
(CtType.STORAGE, "storage_ct_metering_status", ""),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_metering_status", ""),
|
||||
(CtType.BACKFEED, "backfeed_ct_metering_status", ""),
|
||||
(CtType.LOAD, "load_ct_metering_status", ""),
|
||||
(CtType.EVSE, "evse_ct_metering_status", ""),
|
||||
(CtType.PV3P, "pv3p_ct_metering_status", ""),
|
||||
)
|
||||
]
|
||||
+ [
|
||||
@@ -597,11 +557,6 @@ CT_SENSORS = (
|
||||
),
|
||||
(CtType.PRODUCTION, "production_ct_status_flags", ""),
|
||||
(CtType.STORAGE, "storage_ct_status_flags", ""),
|
||||
(CtType.TOTAL_CONSUMPTION, "total_consumption_ct_status_flags", ""),
|
||||
(CtType.BACKFEED, "backfeed_ct_status_flags", ""),
|
||||
(CtType.LOAD, "load_ct_status_flags", ""),
|
||||
(CtType.EVSE, "evse_ct_status_flags", ""),
|
||||
(CtType.PV3P, "pv3p_ct_status_flags", ""),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -160,60 +160,6 @@
|
||||
"available_energy": {
|
||||
"name": "Available battery energy"
|
||||
},
|
||||
"backfeed_ct_current": {
|
||||
"name": "Backfeed CT current"
|
||||
},
|
||||
"backfeed_ct_current_phase": {
|
||||
"name": "Backfeed CT current {phase_name}"
|
||||
},
|
||||
"backfeed_ct_energy_delivered": {
|
||||
"name": "Backfeed CT energy delivered"
|
||||
},
|
||||
"backfeed_ct_energy_delivered_phase": {
|
||||
"name": "Backfeed CT energy delivered {phase_name}"
|
||||
},
|
||||
"backfeed_ct_energy_received": {
|
||||
"name": "Backfeed CT energy received"
|
||||
},
|
||||
"backfeed_ct_energy_received_phase": {
|
||||
"name": "Backfeed CT energy received {phase_name}"
|
||||
},
|
||||
"backfeed_ct_frequency": {
|
||||
"name": "Frequency backfeed CT"
|
||||
},
|
||||
"backfeed_ct_frequency_phase": {
|
||||
"name": "Frequency backfeed CT {phase_name}"
|
||||
},
|
||||
"backfeed_ct_metering_status": {
|
||||
"name": "Metering status backfeed CT"
|
||||
},
|
||||
"backfeed_ct_metering_status_phase": {
|
||||
"name": "Metering status backfeed CT {phase_name}"
|
||||
},
|
||||
"backfeed_ct_power": {
|
||||
"name": "Backfeed CT power"
|
||||
},
|
||||
"backfeed_ct_power_phase": {
|
||||
"name": "Backfeed CT power {phase_name}"
|
||||
},
|
||||
"backfeed_ct_powerfactor": {
|
||||
"name": "Power factor backfeed CT"
|
||||
},
|
||||
"backfeed_ct_powerfactor_phase": {
|
||||
"name": "Power factor backfeed CT {phase_name}"
|
||||
},
|
||||
"backfeed_ct_status_flags": {
|
||||
"name": "Meter status flags active backfeed CT"
|
||||
},
|
||||
"backfeed_ct_status_flags_phase": {
|
||||
"name": "Meter status flags active backfeed CT {phase_name}"
|
||||
},
|
||||
"backfeed_ct_voltage": {
|
||||
"name": "Voltage backfeed CT"
|
||||
},
|
||||
"backfeed_ct_voltage_phase": {
|
||||
"name": "Voltage backfeed CT {phase_name}"
|
||||
},
|
||||
"balanced_net_consumption": {
|
||||
"name": "Balanced net power consumption"
|
||||
},
|
||||
@@ -265,60 +211,6 @@
|
||||
"energy_today": {
|
||||
"name": "[%key:component::enphase_envoy::entity::sensor::daily_production::name%]"
|
||||
},
|
||||
"evse_ct_current": {
|
||||
"name": "EVSE CT current"
|
||||
},
|
||||
"evse_ct_current_phase": {
|
||||
"name": "EVSE CT current {phase_name}"
|
||||
},
|
||||
"evse_ct_energy_delivered": {
|
||||
"name": "EVSE CT energy delivered"
|
||||
},
|
||||
"evse_ct_energy_delivered_phase": {
|
||||
"name": "EVSE CT energy delivered {phase_name}"
|
||||
},
|
||||
"evse_ct_energy_received": {
|
||||
"name": "EVSE CT energy received"
|
||||
},
|
||||
"evse_ct_energy_received_phase": {
|
||||
"name": "EVSE CT energy received {phase_name}"
|
||||
},
|
||||
"evse_ct_frequency": {
|
||||
"name": "Frequency EVSE CT"
|
||||
},
|
||||
"evse_ct_frequency_phase": {
|
||||
"name": "Frequency EVSE CT {phase_name}"
|
||||
},
|
||||
"evse_ct_metering_status": {
|
||||
"name": "Metering status EVSE CT"
|
||||
},
|
||||
"evse_ct_metering_status_phase": {
|
||||
"name": "Metering status EVSE CT {phase_name}"
|
||||
},
|
||||
"evse_ct_power": {
|
||||
"name": "EVSE CT power"
|
||||
},
|
||||
"evse_ct_power_phase": {
|
||||
"name": "EVSE CT power {phase_name}"
|
||||
},
|
||||
"evse_ct_powerfactor": {
|
||||
"name": "Power factor EVSE CT"
|
||||
},
|
||||
"evse_ct_powerfactor_phase": {
|
||||
"name": "Power factor EVSE CT {phase_name}"
|
||||
},
|
||||
"evse_ct_status_flags": {
|
||||
"name": "Meter status flags active EVSE CT"
|
||||
},
|
||||
"evse_ct_status_flags_phase": {
|
||||
"name": "Meter status flags active EVSE CT {phase_name}"
|
||||
},
|
||||
"evse_ct_voltage": {
|
||||
"name": "Voltage EVSE CT"
|
||||
},
|
||||
"evse_ct_voltage_phase": {
|
||||
"name": "Voltage EVSE CT {phase_name}"
|
||||
},
|
||||
"grid_status": {
|
||||
"name": "[%key:component::enphase_envoy::entity::binary_sensor::grid_status::name%]",
|
||||
"state": {
|
||||
@@ -378,60 +270,6 @@
|
||||
"lifetime_production_phase": {
|
||||
"name": "Lifetime energy production {phase_name}"
|
||||
},
|
||||
"load_ct_current": {
|
||||
"name": "Load CT current"
|
||||
},
|
||||
"load_ct_current_phase": {
|
||||
"name": "Load CT current {phase_name}"
|
||||
},
|
||||
"load_ct_energy_delivered": {
|
||||
"name": "Load CT energy delivered"
|
||||
},
|
||||
"load_ct_energy_delivered_phase": {
|
||||
"name": "Load CT energy delivered {phase_name}"
|
||||
},
|
||||
"load_ct_energy_received": {
|
||||
"name": "Load CT energy received"
|
||||
},
|
||||
"load_ct_energy_received_phase": {
|
||||
"name": "Load CT energy received {phase_name}"
|
||||
},
|
||||
"load_ct_frequency": {
|
||||
"name": "Frequency load CT"
|
||||
},
|
||||
"load_ct_frequency_phase": {
|
||||
"name": "Frequency load CT {phase_name}"
|
||||
},
|
||||
"load_ct_metering_status": {
|
||||
"name": "Metering status load CT"
|
||||
},
|
||||
"load_ct_metering_status_phase": {
|
||||
"name": "Metering status load CT {phase_name}"
|
||||
},
|
||||
"load_ct_power": {
|
||||
"name": "Load CT power"
|
||||
},
|
||||
"load_ct_power_phase": {
|
||||
"name": "Load CT power {phase_name}"
|
||||
},
|
||||
"load_ct_powerfactor": {
|
||||
"name": "Power factor load CT"
|
||||
},
|
||||
"load_ct_powerfactor_phase": {
|
||||
"name": "Power factor load CT {phase_name}"
|
||||
},
|
||||
"load_ct_status_flags": {
|
||||
"name": "Meter status flags active load CT"
|
||||
},
|
||||
"load_ct_status_flags_phase": {
|
||||
"name": "Meter status flags active load CT {phase_name}"
|
||||
},
|
||||
"load_ct_voltage": {
|
||||
"name": "Voltage load CT"
|
||||
},
|
||||
"load_ct_voltage_phase": {
|
||||
"name": "Voltage load CT {phase_name}"
|
||||
},
|
||||
"max_capacity": {
|
||||
"name": "Battery capacity"
|
||||
},
|
||||
@@ -493,18 +331,6 @@
|
||||
"production_ct_current_phase": {
|
||||
"name": "Production CT current {phase_name}"
|
||||
},
|
||||
"production_ct_energy_delivered": {
|
||||
"name": "Production CT energy delivered"
|
||||
},
|
||||
"production_ct_energy_delivered_phase": {
|
||||
"name": "Production CT energy delivered {phase_name}"
|
||||
},
|
||||
"production_ct_energy_received": {
|
||||
"name": "Production CT energy received"
|
||||
},
|
||||
"production_ct_energy_received_phase": {
|
||||
"name": "Production CT energy received {phase_name}"
|
||||
},
|
||||
"production_ct_frequency": {
|
||||
"name": "Frequency production CT"
|
||||
},
|
||||
@@ -517,12 +343,6 @@
|
||||
"production_ct_metering_status_phase": {
|
||||
"name": "Metering status production CT {phase_name}"
|
||||
},
|
||||
"production_ct_power": {
|
||||
"name": "Production CT power"
|
||||
},
|
||||
"production_ct_power_phase": {
|
||||
"name": "Production CT power {phase_name}"
|
||||
},
|
||||
"production_ct_powerfactor": {
|
||||
"name": "Power factor production CT"
|
||||
},
|
||||
@@ -541,60 +361,6 @@
|
||||
"production_ct_voltage_phase": {
|
||||
"name": "Voltage production CT {phase_name}"
|
||||
},
|
||||
"pv3p_ct_current": {
|
||||
"name": "PV3P CT current"
|
||||
},
|
||||
"pv3p_ct_current_phase": {
|
||||
"name": "PV3P CT current {phase_name}"
|
||||
},
|
||||
"pv3p_ct_energy_delivered": {
|
||||
"name": "PV3P CT energy delivered"
|
||||
},
|
||||
"pv3p_ct_energy_delivered_phase": {
|
||||
"name": "PV3P CT energy delivered {phase_name}"
|
||||
},
|
||||
"pv3p_ct_energy_received": {
|
||||
"name": "PV3P CT energy received"
|
||||
},
|
||||
"pv3p_ct_energy_received_phase": {
|
||||
"name": "PV3P CT energy received {phase_name}"
|
||||
},
|
||||
"pv3p_ct_frequency": {
|
||||
"name": "Frequency PV3P CT"
|
||||
},
|
||||
"pv3p_ct_frequency_phase": {
|
||||
"name": "Frequency PV3P CT {phase_name}"
|
||||
},
|
||||
"pv3p_ct_metering_status": {
|
||||
"name": "Metering status PV3P CT"
|
||||
},
|
||||
"pv3p_ct_metering_status_phase": {
|
||||
"name": "Metering status PV3P CT {phase_name}"
|
||||
},
|
||||
"pv3p_ct_power": {
|
||||
"name": "PV3P CT power"
|
||||
},
|
||||
"pv3p_ct_power_phase": {
|
||||
"name": "PV3P CT power {phase_name}"
|
||||
},
|
||||
"pv3p_ct_powerfactor": {
|
||||
"name": "Power factor PV3P CT"
|
||||
},
|
||||
"pv3p_ct_powerfactor_phase": {
|
||||
"name": "Power factor PV3P CT {phase_name}"
|
||||
},
|
||||
"pv3p_ct_status_flags": {
|
||||
"name": "Meter status flags active PV3P CT"
|
||||
},
|
||||
"pv3p_ct_status_flags_phase": {
|
||||
"name": "Meter status flags active PV3P CT {phase_name}"
|
||||
},
|
||||
"pv3p_ct_voltage": {
|
||||
"name": "Voltage PV3P CT"
|
||||
},
|
||||
"pv3p_ct_voltage_phase": {
|
||||
"name": "Voltage PV3P CT {phase_name}"
|
||||
},
|
||||
"reserve_energy": {
|
||||
"name": "Reserve battery energy"
|
||||
},
|
||||
@@ -648,60 +414,6 @@
|
||||
},
|
||||
"storage_ct_voltage_phase": {
|
||||
"name": "Voltage storage CT {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_current": {
|
||||
"name": "Total consumption CT current"
|
||||
},
|
||||
"total_consumption_ct_current_phase": {
|
||||
"name": "Total consumption CT current {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_energy_delivered": {
|
||||
"name": "Total consumption CT energy delivered"
|
||||
},
|
||||
"total_consumption_ct_energy_delivered_phase": {
|
||||
"name": "Total consumption CT energy delivered {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_energy_received": {
|
||||
"name": "Total consumption CT energy received"
|
||||
},
|
||||
"total_consumption_ct_energy_received_phase": {
|
||||
"name": "Total consumption CT energy received {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_frequency": {
|
||||
"name": "Frequency total consumption CT"
|
||||
},
|
||||
"total_consumption_ct_frequency_phase": {
|
||||
"name": "Frequency total consumption CT {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_metering_status": {
|
||||
"name": "Metering status total consumption CT"
|
||||
},
|
||||
"total_consumption_ct_metering_status_phase": {
|
||||
"name": "Metering status total consumption CT {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_power": {
|
||||
"name": "Total consumption CT power"
|
||||
},
|
||||
"total_consumption_ct_power_phase": {
|
||||
"name": "Total consumption CT power {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_powerfactor": {
|
||||
"name": "Power factor total consumption CT"
|
||||
},
|
||||
"total_consumption_ct_powerfactor_phase": {
|
||||
"name": "Power factor total consumption CT {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_status_flags": {
|
||||
"name": "Meter status flags active total consumption CT"
|
||||
},
|
||||
"total_consumption_ct_status_flags_phase": {
|
||||
"name": "Meter status flags active total consumption CT {phase_name}"
|
||||
},
|
||||
"total_consumption_ct_voltage": {
|
||||
"name": "Voltage total consumption CT"
|
||||
},
|
||||
"total_consumption_ct_voltage_phase": {
|
||||
"name": "Voltage total consumption CT {phase_name}"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
|
||||
@@ -36,12 +36,12 @@ from homeassistant.const import (
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from .const import ATTR_DURATION, ATTR_PERIOD, DOMAIN, EVOHOME_DATA, EvoService
|
||||
from .const import ATTR_DURATION, ATTR_PERIOD, ATTR_SETPOINT, EVOHOME_DATA, EvoService
|
||||
from .coordinator import EvoDataUpdateCoordinator
|
||||
from .entity import EvoChild, EvoEntity
|
||||
|
||||
@@ -132,24 +132,6 @@ class EvoClimateEntity(EvoEntity, ClimateEntity):
|
||||
_attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT]
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
async def async_clear_zone_override(self) -> None:
|
||||
"""Clear the zone override; only supported by zones."""
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="zone_only_service",
|
||||
translation_placeholders={"service": EvoService.CLEAR_ZONE_OVERRIDE},
|
||||
)
|
||||
|
||||
async def async_set_zone_override(
|
||||
self, setpoint: float, duration: timedelta | None = None
|
||||
) -> None:
|
||||
"""Set the zone override; only supported by zones."""
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="zone_only_service",
|
||||
translation_placeholders={"service": EvoService.SET_ZONE_OVERRIDE},
|
||||
)
|
||||
|
||||
|
||||
class EvoZone(EvoChild, EvoClimateEntity):
|
||||
"""Base for any evohome-compatible heating zone."""
|
||||
@@ -188,22 +170,22 @@ class EvoZone(EvoChild, EvoClimateEntity):
|
||||
| ClimateEntityFeature.TURN_ON
|
||||
)
|
||||
|
||||
async def async_clear_zone_override(self) -> None:
|
||||
"""Clear the zone's override, if any."""
|
||||
await self.coordinator.call_client_api(self._evo_device.reset())
|
||||
async def async_zone_svc_request(self, service: str, data: dict[str, Any]) -> None:
|
||||
"""Process a service request (setpoint override) for a zone."""
|
||||
if service == EvoService.CLEAR_ZONE_OVERRIDE:
|
||||
await self.coordinator.call_client_api(self._evo_device.reset())
|
||||
return
|
||||
|
||||
async def async_set_zone_override(
|
||||
self, setpoint: float, duration: timedelta | None = None
|
||||
) -> None:
|
||||
"""Set the zone's override (mode/setpoint)."""
|
||||
temperature = max(min(setpoint, self.max_temp), self.min_temp)
|
||||
# otherwise it is EvoService.SET_ZONE_OVERRIDE
|
||||
temperature = max(min(data[ATTR_SETPOINT], self.max_temp), self.min_temp)
|
||||
|
||||
if duration is not None:
|
||||
if ATTR_DURATION in data:
|
||||
duration: timedelta = data[ATTR_DURATION]
|
||||
if duration.total_seconds() == 0:
|
||||
await self._update_schedule()
|
||||
until = self.setpoints.get("next_sp_from")
|
||||
else:
|
||||
until = dt_util.now() + duration
|
||||
until = dt_util.now() + data[ATTR_DURATION]
|
||||
else:
|
||||
until = None # indefinitely
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import DOMAIN, EvoService
|
||||
from .coordinator import EvoDataUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -47,12 +47,22 @@ class EvoEntity(CoordinatorEntity[EvoDataUpdateCoordinator]):
|
||||
raise NotImplementedError
|
||||
if payload["unique_id"] != self._attr_unique_id:
|
||||
return
|
||||
if payload["service"] in (
|
||||
EvoService.SET_ZONE_OVERRIDE,
|
||||
EvoService.CLEAR_ZONE_OVERRIDE,
|
||||
):
|
||||
await self.async_zone_svc_request(payload["service"], payload["data"])
|
||||
return
|
||||
await self.async_tcs_svc_request(payload["service"], payload["data"])
|
||||
|
||||
async def async_tcs_svc_request(self, service: str, data: dict[str, Any]) -> None:
|
||||
"""Process a service request (system mode) for a controller."""
|
||||
raise NotImplementedError
|
||||
|
||||
async def async_zone_svc_request(self, service: str, data: dict[str, Any]) -> None:
|
||||
"""Process a service request (setpoint override) for a zone."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Mapping[str, Any]:
|
||||
"""Return the evohome-specific state attributes."""
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any, Final
|
||||
from typing import Final
|
||||
|
||||
from evohomeasync2.const import SZ_CAN_BE_TEMPORARY, SZ_SYSTEM_MODE, SZ_TIMING_MODE
|
||||
from evohomeasync2.schemas.const import (
|
||||
@@ -13,10 +13,9 @@ from evohomeasync2.schemas.const import (
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN
|
||||
from homeassistant.const import ATTR_MODE
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODE
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.helpers import config_validation as cv, service
|
||||
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.service import verify_domain_control
|
||||
|
||||
@@ -26,38 +25,21 @@ from .coordinator import EvoDataUpdateCoordinator
|
||||
# system mode schemas are built dynamically when the services are registered
|
||||
# because supported modes can vary for edge-case systems
|
||||
|
||||
# Zone service schemas (registered as entity services)
|
||||
CLEAR_ZONE_OVERRIDE_SCHEMA: Final[dict[str | vol.Marker, Any]] = {}
|
||||
SET_ZONE_OVERRIDE_SCHEMA: Final[dict[str | vol.Marker, Any]] = {
|
||||
vol.Required(ATTR_SETPOINT): vol.All(
|
||||
vol.Coerce(float), vol.Range(min=4.0, max=35.0)
|
||||
),
|
||||
vol.Optional(ATTR_DURATION): vol.All(
|
||||
cv.time_period,
|
||||
vol.Range(min=timedelta(days=0), max=timedelta(days=1)),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _register_zone_entity_services(hass: HomeAssistant) -> None:
|
||||
"""Register entity-level services for zones."""
|
||||
|
||||
service.async_register_platform_entity_service(
|
||||
hass,
|
||||
DOMAIN,
|
||||
EvoService.CLEAR_ZONE_OVERRIDE,
|
||||
entity_domain=CLIMATE_DOMAIN,
|
||||
schema=CLEAR_ZONE_OVERRIDE_SCHEMA,
|
||||
func="async_clear_zone_override",
|
||||
)
|
||||
service.async_register_platform_entity_service(
|
||||
hass,
|
||||
DOMAIN,
|
||||
EvoService.SET_ZONE_OVERRIDE,
|
||||
entity_domain=CLIMATE_DOMAIN,
|
||||
schema=SET_ZONE_OVERRIDE_SCHEMA,
|
||||
func="async_set_zone_override",
|
||||
)
|
||||
CLEAR_ZONE_OVERRIDE_SCHEMA: Final = vol.Schema(
|
||||
{vol.Required(ATTR_ENTITY_ID): cv.entity_id}
|
||||
)
|
||||
SET_ZONE_OVERRIDE_SCHEMA: Final = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_ENTITY_ID): cv.entity_id,
|
||||
vol.Required(ATTR_SETPOINT): vol.All(
|
||||
vol.Coerce(float), vol.Range(min=4.0, max=35.0)
|
||||
),
|
||||
vol.Optional(ATTR_DURATION): vol.All(
|
||||
cv.time_period,
|
||||
vol.Range(min=timedelta(days=0), max=timedelta(days=1)),
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
@@ -69,6 +51,8 @@ def setup_service_functions(
|
||||
Not all Honeywell TCC-compatible systems support all operating modes. In addition,
|
||||
each mode will require any of four distinct service schemas. This has to be
|
||||
enumerated before registering the appropriate handlers.
|
||||
|
||||
It appears that all TCC-compatible systems support the same three zones modes.
|
||||
"""
|
||||
|
||||
@verify_domain_control(DOMAIN)
|
||||
@@ -88,6 +72,28 @@ def setup_service_functions(
|
||||
}
|
||||
async_dispatcher_send(hass, DOMAIN, payload)
|
||||
|
||||
@verify_domain_control(DOMAIN)
|
||||
async def set_zone_override(call: ServiceCall) -> None:
|
||||
"""Set the zone override (setpoint)."""
|
||||
entity_id = call.data[ATTR_ENTITY_ID]
|
||||
|
||||
registry = er.async_get(hass)
|
||||
registry_entry = registry.async_get(entity_id)
|
||||
|
||||
if registry_entry is None or registry_entry.platform != DOMAIN:
|
||||
raise ValueError(f"'{entity_id}' is not a known {DOMAIN} entity")
|
||||
|
||||
if registry_entry.domain != "climate":
|
||||
raise ValueError(f"'{entity_id}' is not an {DOMAIN} controller/zone")
|
||||
|
||||
payload = {
|
||||
"unique_id": registry_entry.unique_id,
|
||||
"service": call.service,
|
||||
"data": call.data,
|
||||
}
|
||||
|
||||
async_dispatcher_send(hass, DOMAIN, payload)
|
||||
|
||||
assert coordinator.tcs is not None # mypy
|
||||
|
||||
hass.services.async_register(DOMAIN, EvoService.REFRESH_SYSTEM, force_refresh)
|
||||
@@ -150,4 +156,16 @@ def setup_service_functions(
|
||||
schema=vol.Schema(vol.Any(*system_mode_schemas)),
|
||||
)
|
||||
|
||||
_register_zone_entity_services(hass)
|
||||
# The zone modes are consistent across all systems and use the same schema
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
EvoService.CLEAR_ZONE_OVERRIDE,
|
||||
set_zone_override,
|
||||
schema=CLEAR_ZONE_OVERRIDE_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
EvoService.SET_ZONE_OVERRIDE,
|
||||
set_zone_override,
|
||||
schema=SET_ZONE_OVERRIDE_SCHEMA,
|
||||
)
|
||||
|
||||
@@ -28,11 +28,14 @@ reset_system:
|
||||
refresh_system:
|
||||
|
||||
set_zone_override:
|
||||
target:
|
||||
entity:
|
||||
integration: evohome
|
||||
domain: climate
|
||||
fields:
|
||||
entity_id:
|
||||
required: true
|
||||
example: climate.bathroom
|
||||
selector:
|
||||
entity:
|
||||
integration: evohome
|
||||
domain: climate
|
||||
setpoint:
|
||||
required: true
|
||||
selector:
|
||||
@@ -46,7 +49,10 @@ set_zone_override:
|
||||
object:
|
||||
|
||||
clear_zone_override:
|
||||
target:
|
||||
entity:
|
||||
integration: evohome
|
||||
domain: climate
|
||||
fields:
|
||||
entity_id:
|
||||
required: true
|
||||
selector:
|
||||
entity:
|
||||
integration: evohome
|
||||
domain: climate
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"exceptions": {
|
||||
"zone_only_service": {
|
||||
"message": "Only zones support the `{service}` action"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"clear_zone_override": {
|
||||
"description": "Sets a zone to follow its schedule.",
|
||||
"fields": {
|
||||
"entity_id": {
|
||||
"description": "[%key:component::evohome::services::set_zone_override::fields::entity_id::description%]",
|
||||
"name": "[%key:component::evohome::services::set_zone_override::fields::entity_id::name%]"
|
||||
}
|
||||
},
|
||||
"name": "Clear zone override"
|
||||
},
|
||||
"refresh_system": {
|
||||
@@ -42,6 +43,10 @@
|
||||
"description": "The zone will revert to its schedule after this time. If 0 the change is until the next scheduled setpoint.",
|
||||
"name": "Duration"
|
||||
},
|
||||
"entity_id": {
|
||||
"description": "The entity ID of the Evohome zone.",
|
||||
"name": "Entity"
|
||||
},
|
||||
"setpoint": {
|
||||
"description": "The temperature to be used instead of the scheduled setpoint.",
|
||||
"name": "Setpoint"
|
||||
|
||||
@@ -45,10 +45,6 @@ async def async_user_store(hass: HomeAssistant, user_id: str) -> UserStore:
|
||||
except BaseException as ex:
|
||||
del stores[user_id]
|
||||
future.set_exception(ex)
|
||||
# Ensure the future is marked as retrieved
|
||||
# since if there is no concurrent call it
|
||||
# will otherwise never be retrieved.
|
||||
future.exception()
|
||||
raise
|
||||
future.set_result(store)
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
"battery_charge_discharge_state": {
|
||||
"name": "Battery charge/discharge state",
|
||||
"state": {
|
||||
"charging": "[%key:common::state::charging%]",
|
||||
"discharging": "[%key:common::state::discharging%]",
|
||||
"charging": "Charging",
|
||||
"discharging": "Discharging",
|
||||
"static": "Static"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,13 +5,13 @@ from __future__ import annotations
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_API_TOKEN, CONF_URL
|
||||
from homeassistant.const import CONF_API_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import PortainerConfigEntry
|
||||
from .coordinator import PortainerCoordinator
|
||||
|
||||
TO_REDACT = [CONF_API_TOKEN, CONF_URL]
|
||||
TO_REDACT = [CONF_API_TOKEN]
|
||||
|
||||
|
||||
def _serialize_coordinator(coordinator: PortainerCoordinator) -> dict[str, Any]:
|
||||
|
||||
@@ -38,12 +38,6 @@
|
||||
"ssl": "[%key:common::config_flow::data::ssl%]",
|
||||
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
|
||||
},
|
||||
"data_description": {
|
||||
"group": "[%key:component::sma::config::step::user::data_description::group%]",
|
||||
"host": "[%key:component::sma::config::step::user::data_description::host%]",
|
||||
"ssl": "[%key:component::sma::config::step::user::data_description::ssl%]",
|
||||
"verify_ssl": "[%key:component::sma::config::step::user::data_description::verify_ssl%]"
|
||||
},
|
||||
"description": "Use the following form to reconfigure your SMA device.",
|
||||
"title": "Reconfigure SMA Solar Integration"
|
||||
},
|
||||
@@ -56,11 +50,7 @@
|
||||
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
|
||||
},
|
||||
"data_description": {
|
||||
"group": "The group of your SMA device, where the Modbus connection is configured",
|
||||
"host": "The hostname or IP address of your SMA device",
|
||||
"password": "The password for your SMA device",
|
||||
"ssl": "Whether to use SSL to connect to your SMA device. This is required for newer SMA devices, but older devices do not support SSL",
|
||||
"verify_ssl": "Whether to verify SSL certificates. Disable only if you have a self-signed certificate"
|
||||
"host": "The hostname or IP address of your SMA device."
|
||||
},
|
||||
"description": "Enter your SMA device information.",
|
||||
"title": "Set up SMA Solar"
|
||||
|
||||
@@ -177,12 +177,6 @@
|
||||
"on": "mdi:lightbulb-on"
|
||||
}
|
||||
},
|
||||
"do_not_disturb": {
|
||||
"default": "mdi:minus-circle-off",
|
||||
"state": {
|
||||
"on": "mdi:minus-circle"
|
||||
}
|
||||
},
|
||||
"dry_plus": {
|
||||
"default": "mdi:heat-wave"
|
||||
},
|
||||
|
||||
@@ -95,7 +95,6 @@ ROBOT_CLEANER_TURBO_MODE_STATE_MAP = {
|
||||
|
||||
ROBOT_CLEANER_MOVEMENT_MAP = {
|
||||
"powerOff": "off",
|
||||
"washingMop": "washing_mop",
|
||||
}
|
||||
|
||||
OVEN_MODE = {
|
||||
@@ -881,7 +880,6 @@ CAPABILITY_TO_SENSORS: dict[
|
||||
"after",
|
||||
"cleaning",
|
||||
"pause",
|
||||
"washing_mop",
|
||||
],
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
value_fn=lambda value: ROBOT_CLEANER_MOVEMENT_MAP.get(value, value),
|
||||
|
||||
@@ -718,8 +718,7 @@
|
||||
"off": "[%key:common::state::off%]",
|
||||
"pause": "[%key:common::state::paused%]",
|
||||
"point": "Point",
|
||||
"reserve": "Reserve",
|
||||
"washing_mop": "Washing mop"
|
||||
"reserve": "Reserve"
|
||||
}
|
||||
},
|
||||
"robot_cleaner_turbo_mode": {
|
||||
@@ -859,9 +858,6 @@
|
||||
"display_lighting": {
|
||||
"name": "Display lighting"
|
||||
},
|
||||
"do_not_disturb": {
|
||||
"name": "Do not disturb"
|
||||
},
|
||||
"dry_plus": {
|
||||
"name": "Dry plus"
|
||||
},
|
||||
|
||||
@@ -162,14 +162,6 @@ CAPABILITY_TO_SWITCHES: dict[Capability | str, SmartThingsSwitchEntityDescriptio
|
||||
status_attribute=Attribute.STATUS,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
),
|
||||
Capability.CUSTOM_DO_NOT_DISTURB_MODE: SmartThingsSwitchEntityDescription(
|
||||
key=Capability.CUSTOM_DO_NOT_DISTURB_MODE,
|
||||
translation_key="do_not_disturb",
|
||||
status_attribute=Attribute.DO_NOT_DISTURB,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
on_command=Command.DO_NOT_DISTURB_ON,
|
||||
off_command=Command.DO_NOT_DISTURB_OFF,
|
||||
),
|
||||
}
|
||||
DISHWASHER_WASHING_OPTIONS_TO_SWITCHES: dict[
|
||||
Attribute | str, SmartThingsDishwasherWashingOptionSwitchEntityDescription
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["switchbot"],
|
||||
"quality_scale": "gold",
|
||||
"requirements": ["PySwitchbot==1.1.0"]
|
||||
"requirements": ["PySwitchbot==1.0.0"]
|
||||
}
|
||||
|
||||
@@ -236,6 +236,12 @@ class StateVacuumEntity(
|
||||
if self.__vacuum_legacy_battery_icon:
|
||||
self._report_deprecated_battery_properties("battery_icon")
|
||||
|
||||
@callback
|
||||
def async_write_ha_state(self) -> None:
|
||||
"""Write the state to the state machine."""
|
||||
super().async_write_ha_state()
|
||||
self._async_check_segments_issues()
|
||||
|
||||
@callback
|
||||
def async_registry_entry_updated(self) -> None:
|
||||
"""Run when the entity registry entry has been updated."""
|
||||
@@ -508,6 +514,43 @@ class StateVacuumEntity(
|
||||
return
|
||||
|
||||
options: Mapping[str, Any] = self.registry_entry.options.get(DOMAIN, {})
|
||||
should_have_not_configured_issue = (
|
||||
VacuumEntityFeature.CLEAN_AREA in self.supported_features
|
||||
and options.get("area_mapping") is None
|
||||
)
|
||||
|
||||
if (
|
||||
should_have_not_configured_issue
|
||||
and not self._segments_not_configured_issue_created
|
||||
):
|
||||
issue_id = (
|
||||
f"{ISSUE_SEGMENTS_MAPPING_NOT_CONFIGURED}_{self.registry_entry.id}"
|
||||
)
|
||||
ir.async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
issue_id,
|
||||
data={
|
||||
"entry_id": self.registry_entry.id,
|
||||
"entity_id": self.entity_id,
|
||||
},
|
||||
is_fixable=False,
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
translation_key=ISSUE_SEGMENTS_MAPPING_NOT_CONFIGURED,
|
||||
translation_placeholders={
|
||||
"entity_id": self.entity_id,
|
||||
},
|
||||
)
|
||||
self._segments_not_configured_issue_created = True
|
||||
elif (
|
||||
not should_have_not_configured_issue
|
||||
and self._segments_not_configured_issue_created
|
||||
):
|
||||
issue_id = (
|
||||
f"{ISSUE_SEGMENTS_MAPPING_NOT_CONFIGURED}_{self.registry_entry.id}"
|
||||
)
|
||||
ir.async_delete_issue(self.hass, DOMAIN, issue_id)
|
||||
self._segments_not_configured_issue_created = False
|
||||
|
||||
if self._segments_changed_last_seen is not None and (
|
||||
VacuumEntityFeature.CLEAN_AREA not in self.supported_features
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
"segments_changed": {
|
||||
"description": "",
|
||||
"title": "Vacuum segments have changed for {entity_id}"
|
||||
},
|
||||
"segments_mapping_not_configured": {
|
||||
"description": "",
|
||||
"title": "Vacuum segment mapping not configured for {entity_id}"
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"domain": "wled",
|
||||
"name": "WLED",
|
||||
"codeowners": ["@frenck", "@mik-laj"],
|
||||
"codeowners": ["@frenck"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/wled",
|
||||
"integration_type": "device",
|
||||
|
||||
@@ -32,11 +32,8 @@ def write_utf8_file_atomic(
|
||||
Using this function frequently will significantly
|
||||
negatively impact performance.
|
||||
"""
|
||||
encoding = "utf-8" if "b" not in mode else None
|
||||
try:
|
||||
with AtomicWriter( # type: ignore[call-arg] # atomicwrites-stubs is outdated, encoding is a valid kwarg
|
||||
filename, mode=mode, overwrite=True, encoding=encoding
|
||||
).open() as fdesc:
|
||||
with AtomicWriter(filename, mode=mode, overwrite=True).open() as fdesc:
|
||||
if not private:
|
||||
os.fchmod(fdesc.fileno(), 0o644)
|
||||
fdesc.write(utf8_data)
|
||||
|
||||
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@@ -83,7 +83,7 @@ PyRMVtransport==0.3.3
|
||||
PySrDaliGateway==0.19.3
|
||||
|
||||
# homeassistant.components.switchbot
|
||||
PySwitchbot==1.1.0
|
||||
PySwitchbot==1.0.0
|
||||
|
||||
# homeassistant.components.switchmate
|
||||
PySwitchmate==0.5.1
|
||||
|
||||
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@@ -83,7 +83,7 @@ PyRMVtransport==0.3.3
|
||||
PySrDaliGateway==0.19.3
|
||||
|
||||
# homeassistant.components.switchbot
|
||||
PySwitchbot==1.1.0
|
||||
PySwitchbot==1.0.0
|
||||
|
||||
# homeassistant.components.syncthru
|
||||
PySyncThru==0.8.0
|
||||
|
||||
@@ -213,7 +213,6 @@ async def test_reauth_flow_scenario(
|
||||
ap_fixture: AirOSData,
|
||||
mock_airos_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_setup_entry: AsyncMock,
|
||||
) -> None:
|
||||
"""Test successful reauthentication."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
@@ -221,15 +220,11 @@ async def test_reauth_flow_scenario(
|
||||
mock_airos_client.login.side_effect = AirOSConnectionAuthenticationError
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.airos.config_flow.async_get_firmware_data",
|
||||
side_effect=AirOSConnectionAuthenticationError,
|
||||
):
|
||||
flow = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_REAUTH, "entry_id": mock_config_entry.entry_id},
|
||||
data=mock_config_entry.data,
|
||||
)
|
||||
flow = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_REAUTH, "entry_id": mock_config_entry.entry_id},
|
||||
data=mock_config_entry.data,
|
||||
)
|
||||
|
||||
assert flow["type"] == FlowResultType.FORM
|
||||
assert flow["step_id"] == REAUTH_STEP
|
||||
@@ -241,22 +236,20 @@ async def test_reauth_flow_scenario(
|
||||
hostname=ap_fixture.host.hostname,
|
||||
)
|
||||
|
||||
mock_firmware = AsyncMock(return_value=valid_data)
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.airos.config_flow.async_get_firmware_data",
|
||||
new=mock_firmware,
|
||||
new=AsyncMock(return_value=valid_data),
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.airos.async_get_firmware_data",
|
||||
new=mock_firmware,
|
||||
new=AsyncMock(return_value=valid_data),
|
||||
),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow["flow_id"],
|
||||
user_input={CONF_PASSWORD: NEW_PASSWORD},
|
||||
)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
# Always test resolution
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
|
||||
@@ -19,16 +19,18 @@ async def test_setup_entry(config_entry_setup: MockConfigEntry) -> None:
|
||||
async def test_setup_entry_fails(
|
||||
hass: HomeAssistant, config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test failed setup of entry."""
|
||||
"""Test successful setup of entry."""
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.axis.get_axis_api",
|
||||
side_effect=axis.CannotConnect,
|
||||
):
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
mock_device = Mock()
|
||||
mock_device.async_setup = AsyncMock(return_value=False)
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
with patch.object(axis, "AxisHub") as mock_device_class:
|
||||
mock_device_class.return_value = mock_device
|
||||
|
||||
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
|
||||
async def test_unload_entry(
|
||||
|
||||
@@ -13,11 +13,7 @@ import pytest
|
||||
from voluptuous import MultipleInvalid
|
||||
|
||||
from homeassistant.components.blue_current import async_setup_entry
|
||||
from homeassistant.components.blue_current.const import (
|
||||
CHARGING_CARD_ID,
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
)
|
||||
from homeassistant.components.blue_current.const import CHARGING_CARD_ID, DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_DEVICE_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -124,7 +120,7 @@ async def test_start_charging_action(
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{
|
||||
CONF_DEVICE_ID: list(device_registry.devices)[0],
|
||||
CHARGING_CARD_ID: "TEST_CARD",
|
||||
@@ -144,7 +140,7 @@ async def test_start_charging_action_without_card(
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{
|
||||
CONF_DEVICE_ID: list(device_registry.devices)[0],
|
||||
},
|
||||
@@ -166,7 +162,7 @@ async def test_start_charging_action_errors(
|
||||
# No device id
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{},
|
||||
blocking=True,
|
||||
)
|
||||
@@ -175,7 +171,7 @@ async def test_start_charging_action_errors(
|
||||
# Invalid device id
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{CONF_DEVICE_ID: "INVALID"},
|
||||
blocking=True,
|
||||
)
|
||||
@@ -192,7 +188,7 @@ async def test_start_charging_action_errors(
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{
|
||||
CONF_DEVICE_ID: list(device_registry.devices)[0],
|
||||
},
|
||||
@@ -212,7 +208,7 @@ async def test_start_charging_action_errors(
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_START_CHARGE_SESSION,
|
||||
"start_charge_session",
|
||||
{
|
||||
CONF_DEVICE_ID: list(device_registry.devices)[0],
|
||||
},
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
'object_id_base': 'Total energy',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
@@ -19,7 +18,6 @@ ENTITY_OUTSIDE_TEMP = "sensor.bsb_lan_outside_temperature"
|
||||
ENTITY_TOTAL_ENERGY = "sensor.bsb_lan_total_energy"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_sensor_entity_properties(
|
||||
hass: HomeAssistant,
|
||||
mock_bsblan: AsyncMock,
|
||||
|
||||
@@ -10,6 +10,10 @@ import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.bsblan.const import DOMAIN
|
||||
from homeassistant.components.bsblan.services import (
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
async_setup_services,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
@@ -130,7 +134,7 @@ async def test_set_hot_water_schedule(
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
service_call_data,
|
||||
blocking=True,
|
||||
)
|
||||
@@ -159,7 +163,7 @@ async def test_invalid_device_id(
|
||||
with pytest.raises(ServiceValidationError) as exc_info:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": "invalid_device_id",
|
||||
"monday_slots": [
|
||||
@@ -172,12 +176,11 @@ async def test_invalid_device_id(
|
||||
assert exc_info.value.translation_key == "invalid_device_id"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("setup_integration")
|
||||
@pytest.mark.parametrize(
|
||||
("service_name", "service_data"),
|
||||
[
|
||||
(
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{"monday_slots": [{"start_time": time(6, 0), "end_time": time(8, 0)}]},
|
||||
),
|
||||
("sync_time", {}),
|
||||
@@ -202,6 +205,9 @@ async def test_no_config_entry_for_device(
|
||||
name="Other Device",
|
||||
)
|
||||
|
||||
# Register the bsblan service without setting up any bsblan config entry
|
||||
async_setup_services(hass)
|
||||
|
||||
with pytest.raises(ServiceValidationError) as exc_info:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@@ -216,15 +222,26 @@ async def test_no_config_entry_for_device(
|
||||
async def test_config_entry_not_loaded(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
device_entry: dr.DeviceEntry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test error when config entry is not loaded."""
|
||||
await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
# Add the config entry but don't set it up (so it stays in NOT_LOADED state)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
# Create the device manually since setup won't run
|
||||
device_entry = device_registry.async_get_or_create(
|
||||
config_entry_id=mock_config_entry.entry_id,
|
||||
identifiers={(DOMAIN, TEST_DEVICE_MAC)},
|
||||
name="BSB-LAN Device",
|
||||
)
|
||||
|
||||
# Register the service
|
||||
async_setup_services(hass)
|
||||
|
||||
with pytest.raises(ServiceValidationError) as exc_info:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -249,7 +266,7 @@ async def test_api_error(
|
||||
with pytest.raises(HomeAssistantError) as exc_info:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -285,7 +302,7 @@ async def test_time_validation_errors(
|
||||
with pytest.raises(ServiceValidationError) as exc_info:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -308,7 +325,7 @@ async def test_unprovided_days_are_none(
|
||||
# Only provide Monday and Tuesday, leave other days unprovided
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -352,7 +369,7 @@ async def test_string_time_formats(
|
||||
# Test with string time formats
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -389,7 +406,7 @@ async def test_non_standard_time_types(
|
||||
with pytest.raises(vol.MultipleInvalid):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_hot_water_schedule",
|
||||
SERVICE_SET_HOT_WATER_SCHEDULE,
|
||||
{
|
||||
"device_id": device_entry.id,
|
||||
"monday_slots": [
|
||||
@@ -407,7 +424,7 @@ async def test_async_setup_services(
|
||||
) -> None:
|
||||
"""Test service registration."""
|
||||
# Verify service doesn't exist initially
|
||||
assert not hass.services.has_service(DOMAIN, "set_hot_water_schedule")
|
||||
assert not hass.services.has_service(DOMAIN, SERVICE_SET_HOT_WATER_SCHEDULE)
|
||||
|
||||
# Set up the integration
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
@@ -415,7 +432,7 @@ async def test_async_setup_services(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify service is now registered
|
||||
assert hass.services.has_service(DOMAIN, "set_hot_water_schedule")
|
||||
assert hass.services.has_service(DOMAIN, SERVICE_SET_HOT_WATER_SCHEDULE)
|
||||
|
||||
|
||||
async def test_sync_time_service(
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
"""Tests for the Daikin config flow."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from ipaddress import ip_address
|
||||
from unittest.mock import AsyncMock, PropertyMock, patch
|
||||
from unittest.mock import PropertyMock, patch
|
||||
|
||||
from aiohttp import ClientError, web_exceptions
|
||||
from pydaikin.exceptions import DaikinException
|
||||
@@ -21,15 +20,6 @@ MAC = "AABBCCDDEEFF"
|
||||
HOST = "127.0.0.1"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
with patch(
|
||||
"homeassistant.components.daikin.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
yield mock_setup
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_daikin():
|
||||
"""Mock pydaikin."""
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
"""Tests for emulated_roku config flow."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.emulated_roku import config_flow
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -13,15 +8,6 @@ from homeassistant.data_entry_flow import FlowResultType
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
with patch(
|
||||
"homeassistant.components.emulated_roku.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
yield mock_setup
|
||||
|
||||
|
||||
async def test_flow_works(hass: HomeAssistant) -> None:
|
||||
"""Test that config flow works."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
||||
@@ -196,66 +196,6 @@
|
||||
"measurement_type": "storage",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"backfeed": {
|
||||
"eid": "100000040",
|
||||
"timestamp": 1708006120,
|
||||
"energy_delivered": 41234,
|
||||
"energy_received": 42345,
|
||||
"active_power": 104,
|
||||
"power_factor": 0.24,
|
||||
"voltage": 114,
|
||||
"current": 0.5,
|
||||
"frequency": 50.4,
|
||||
"state": "enabled",
|
||||
"measurement_type": "backfeed",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"load": {
|
||||
"eid": "100000050",
|
||||
"timestamp": 1708006120,
|
||||
"energy_delivered": 51234,
|
||||
"energy_received": 52345,
|
||||
"active_power": 105,
|
||||
"power_factor": 0.25,
|
||||
"voltage": 115,
|
||||
"current": 0.6,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "load",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"evse": {
|
||||
"eid": "100000060",
|
||||
"timestamp": 1708006120,
|
||||
"energy_delivered": 61234,
|
||||
"energy_received": 62345,
|
||||
"active_power": 106,
|
||||
"power_factor": 0.26,
|
||||
"voltage": 116,
|
||||
"current": 0.7,
|
||||
"frequency": 50.7,
|
||||
"state": "enabled",
|
||||
"measurement_type": "evse",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"pv3p": {
|
||||
"eid": "100000070",
|
||||
"timestamp": 1708006120,
|
||||
"energy_delivered": 71234,
|
||||
"energy_received": 72345,
|
||||
"active_power": 107,
|
||||
"power_factor": 0.27,
|
||||
"voltage": 117,
|
||||
"current": 0.8,
|
||||
"frequency": 50.8,
|
||||
"state": "enabled",
|
||||
"measurement_type": "pv3p",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"ctmeters_phases": {
|
||||
@@ -399,194 +339,6 @@
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"backfeed": {
|
||||
"L1": {
|
||||
"eid": "100000041",
|
||||
"timestamp": 1708006121,
|
||||
"energy_delivered": 412341,
|
||||
"energy_received": 423451,
|
||||
"active_power": 114,
|
||||
"power_factor": 0.24,
|
||||
"voltage": 114,
|
||||
"current": 4.1,
|
||||
"frequency": 50.4,
|
||||
"state": "enabled",
|
||||
"measurement_type": "backfeed",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000042",
|
||||
"timestamp": 1708006122,
|
||||
"energy_delivered": 412342,
|
||||
"energy_received": 423452,
|
||||
"active_power": 124,
|
||||
"power_factor": 0.24,
|
||||
"voltage": 114,
|
||||
"current": 4.2,
|
||||
"frequency": 50.4,
|
||||
"state": "enabled",
|
||||
"measurement_type": "backfeed",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000042",
|
||||
"timestamp": 1708006123,
|
||||
"energy_delivered": 412343,
|
||||
"energy_received": 423453,
|
||||
"active_power": 134,
|
||||
"power_factor": 0.24,
|
||||
"voltage": 114,
|
||||
"current": 4.3,
|
||||
"frequency": 50.4,
|
||||
"state": "enabled",
|
||||
"measurement_type": "backfeed",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"load": {
|
||||
"L1": {
|
||||
"eid": "100000051",
|
||||
"timestamp": 1708006121,
|
||||
"energy_delivered": 512341,
|
||||
"energy_received": 523451,
|
||||
"active_power": 115,
|
||||
"power_factor": 0.25,
|
||||
"voltage": 115,
|
||||
"current": 5.1,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "load",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000052",
|
||||
"timestamp": 1708006122,
|
||||
"energy_delivered": 512342,
|
||||
"energy_received": 523452,
|
||||
"active_power": 125,
|
||||
"power_factor": 0.25,
|
||||
"voltage": 115,
|
||||
"current": 5.2,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "load",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000052",
|
||||
"timestamp": 1708006123,
|
||||
"energy_delivered": 512343,
|
||||
"energy_received": 523453,
|
||||
"active_power": 135,
|
||||
"power_factor": 0.25,
|
||||
"voltage": 115,
|
||||
"current": 5.3,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "load",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"evse": {
|
||||
"L1": {
|
||||
"eid": "100000061",
|
||||
"timestamp": 1708006121,
|
||||
"energy_delivered": 612341,
|
||||
"energy_received": 623451,
|
||||
"active_power": 116,
|
||||
"power_factor": 0.26,
|
||||
"voltage": 116,
|
||||
"current": 6.1,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "evse",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000062",
|
||||
"timestamp": 1708006122,
|
||||
"energy_delivered": 612342,
|
||||
"energy_received": 623452,
|
||||
"active_power": 126,
|
||||
"power_factor": 0.26,
|
||||
"voltage": 116,
|
||||
"current": 6.2,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "evse",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000063",
|
||||
"timestamp": 1708006123,
|
||||
"energy_delivered": 612343,
|
||||
"energy_received": 623453,
|
||||
"active_power": 136,
|
||||
"power_factor": 0.26,
|
||||
"voltage": 116,
|
||||
"current": 6.3,
|
||||
"frequency": 50.6,
|
||||
"state": "enabled",
|
||||
"measurement_type": "evse",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
},
|
||||
"pv3p": {
|
||||
"L1": {
|
||||
"eid": "100000071",
|
||||
"timestamp": 1708006127,
|
||||
"energy_delivered": 712341,
|
||||
"energy_received": 723451,
|
||||
"active_power": 117,
|
||||
"power_factor": 0.27,
|
||||
"voltage": 117,
|
||||
"current": 7.1,
|
||||
"frequency": 50.7,
|
||||
"state": "enabled",
|
||||
"measurement_type": "pv3p",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L2": {
|
||||
"eid": "100000072",
|
||||
"timestamp": 1708006122,
|
||||
"energy_delivered": 712342,
|
||||
"energy_received": 723452,
|
||||
"active_power": 127,
|
||||
"power_factor": 0.27,
|
||||
"voltage": 117,
|
||||
"current": 7.2,
|
||||
"frequency": 50.7,
|
||||
"state": "enabled",
|
||||
"measurement_type": "pv3p",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
},
|
||||
"L3": {
|
||||
"eid": "100000073",
|
||||
"timestamp": 1708006123,
|
||||
"energy_delivered": 712343,
|
||||
"energy_received": 723453,
|
||||
"active_power": 137,
|
||||
"power_factor": 0.27,
|
||||
"voltage": 117,
|
||||
"current": 7.3,
|
||||
"frequency": 50.7,
|
||||
"state": "enabled",
|
||||
"measurement_type": "pv3p",
|
||||
"metering_status": "normal",
|
||||
"status_flags": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"ctmeter_production": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,6 @@ from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pyenphase.exceptions import EnvoyError
|
||||
from pyenphase.models.meters import CtType
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
@@ -119,68 +118,6 @@ async def test_entry_diagnostics_with_interface_information(
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
# fix order of entities by device to avoid snapshot assertion
|
||||
# failures due to changed id based order between test runs
|
||||
diagnostics = await get_diagnostics_for_config_entry(
|
||||
assert await get_diagnostics_for_config_entry(
|
||||
hass, hass_client, config_entry
|
||||
)
|
||||
diagnostics["envoy_entities_by_device"] = [
|
||||
{
|
||||
"device": device_entities["device"],
|
||||
"entities": sorted(
|
||||
device_entities["entities"], key=lambda e: e["entity"]["entity_id"]
|
||||
),
|
||||
}
|
||||
for device_entities in sorted(
|
||||
diagnostics["envoy_entities_by_device"],
|
||||
key=lambda e: e["device"]["identifiers"],
|
||||
)
|
||||
]
|
||||
assert diagnostics == snapshot(exclude=limit_diagnostic_attrs)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mock_envoy", "ctpresent"),
|
||||
[
|
||||
("envoy", ()),
|
||||
("envoy_1p_metered", (CtType.PRODUCTION, CtType.NET_CONSUMPTION)),
|
||||
("envoy_acb_batt", (CtType.PRODUCTION, CtType.NET_CONSUMPTION)),
|
||||
("envoy_eu_batt", (CtType.PRODUCTION, CtType.NET_CONSUMPTION)),
|
||||
(
|
||||
"envoy_metered_batt_relay",
|
||||
(
|
||||
CtType.PRODUCTION,
|
||||
CtType.NET_CONSUMPTION,
|
||||
CtType.STORAGE,
|
||||
CtType.BACKFEED,
|
||||
CtType.LOAD,
|
||||
CtType.EVSE,
|
||||
CtType.PV3P,
|
||||
),
|
||||
),
|
||||
("envoy_nobatt_metered_3p", (CtType.PRODUCTION, CtType.NET_CONSUMPTION)),
|
||||
("envoy_tot_cons_metered", (CtType.PRODUCTION, CtType.TOTAL_CONSUMPTION)),
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
async def test_entry_diagnostics_ct_presence(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_envoy: AsyncMock,
|
||||
ctpresent: tuple[CtType, ...],
|
||||
) -> None:
|
||||
"""Test config entry diagnostics including interface data."""
|
||||
await setup_integration(hass, config_entry)
|
||||
|
||||
diagnostics = await get_diagnostics_for_config_entry(
|
||||
hass, hass_client, config_entry
|
||||
)
|
||||
# are expected ct in diagnostic report
|
||||
for ct in ctpresent:
|
||||
assert diagnostics["envoy_model_data"]["ctmeters"][ct]
|
||||
|
||||
# are no more ct in diagnostic report as in ctpresent
|
||||
for ct in diagnostics["envoy_model_data"]["ctmeters"]:
|
||||
assert ct in ctpresent
|
||||
) == snapshot(exclude=limit_diagnostic_attrs)
|
||||
|
||||
@@ -680,186 +680,6 @@ async def test_sensor_storage_ct_phase_data(
|
||||
assert entity_state.state == target
|
||||
|
||||
|
||||
CT_NAMES_FLOAT = (
|
||||
"<cttype>_ct_energy_delivered",
|
||||
"<cttype>_ct_energy_received",
|
||||
"<cttype>_ct_power",
|
||||
"frequency_<cttype>_ct",
|
||||
"voltage_<cttype>_ct",
|
||||
"<cttype>_ct_current",
|
||||
"power_factor_<cttype>_ct",
|
||||
"meter_status_flags_active_<cttype>_ct",
|
||||
)
|
||||
CT_NAMES_STR = ("metering_status_<cttype>_ct",)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("cttype", "mock_envoy"),
|
||||
[
|
||||
(CtType.PRODUCTION, "envoy_metered_batt_relay"),
|
||||
(CtType.TOTAL_CONSUMPTION, "envoy_tot_cons_metered"),
|
||||
(CtType.BACKFEED, "envoy_metered_batt_relay"),
|
||||
(CtType.LOAD, "envoy_metered_batt_relay"),
|
||||
(CtType.EVSE, "envoy_metered_batt_relay"),
|
||||
(CtType.PV3P, "envoy_metered_batt_relay"),
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_sensor_ct_data(
|
||||
hass: HomeAssistant,
|
||||
mock_envoy: AsyncMock,
|
||||
config_entry: MockConfigEntry,
|
||||
cttype: CtType,
|
||||
) -> None:
|
||||
"""Test ct entities values."""
|
||||
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, config_entry)
|
||||
|
||||
sn = mock_envoy.serial_number
|
||||
ENTITY_BASE: str = f"{Platform.SENSOR}.envoy_{sn}"
|
||||
|
||||
data = mock_envoy.data.ctmeters[cttype]
|
||||
|
||||
CT_TARGETS_FLOAT = (
|
||||
data.energy_delivered / 1000000.0,
|
||||
data.energy_received / 1000000.0,
|
||||
data.active_power / 1000.0,
|
||||
data.frequency,
|
||||
data.voltage,
|
||||
data.current,
|
||||
data.power_factor,
|
||||
len(data.status_flags),
|
||||
)
|
||||
count_names: int = 0
|
||||
|
||||
for name, target in list(
|
||||
zip(
|
||||
[
|
||||
entity.replace("<cttype>", cttype).replace("-", "_")
|
||||
for entity in CT_NAMES_FLOAT
|
||||
],
|
||||
CT_TARGETS_FLOAT,
|
||||
strict=False,
|
||||
)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert float(entity_state.state) == target
|
||||
count_names += 1
|
||||
|
||||
CT_TARGETS_STR = (data.metering_status,)
|
||||
for name, target in list(
|
||||
zip(
|
||||
[
|
||||
entity.replace("<cttype>", cttype).replace("-", "_")
|
||||
for entity in CT_NAMES_STR
|
||||
],
|
||||
CT_TARGETS_STR,
|
||||
strict=False,
|
||||
)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert entity_state.state == target
|
||||
count_names += 1
|
||||
|
||||
# verify we're testing them all
|
||||
assert len(CT_NAMES_FLOAT) + len(CT_NAMES_STR) == count_names
|
||||
|
||||
|
||||
CT_NAMES_FLOAT_PHASE = [
|
||||
f"{name}_{phase.lower()}" for phase in PHASENAMES for name in (CT_NAMES_FLOAT)
|
||||
]
|
||||
|
||||
CT_NAMES_STR_PHASE = [
|
||||
f"{name}_{phase.lower()}" for phase in PHASENAMES for name in (CT_NAMES_STR)
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"cttype",
|
||||
[
|
||||
CtType.PRODUCTION,
|
||||
CtType.BACKFEED,
|
||||
CtType.LOAD,
|
||||
CtType.EVSE,
|
||||
CtType.PV3P,
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("mock_envoy"),
|
||||
[
|
||||
"envoy_metered_batt_relay",
|
||||
],
|
||||
indirect=["mock_envoy"],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_sensor_ct_phase_data(
|
||||
hass: HomeAssistant,
|
||||
mock_envoy: AsyncMock,
|
||||
config_entry: MockConfigEntry,
|
||||
cttype: CtType,
|
||||
) -> None:
|
||||
"""Test ct phase entities values."""
|
||||
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, config_entry)
|
||||
|
||||
sn = mock_envoy.serial_number
|
||||
ENTITY_BASE: str = f"{Platform.SENSOR}.envoy_{sn}"
|
||||
|
||||
CT_NAMES_FLOAT_PHASE_TARGET = chain(
|
||||
*[
|
||||
(
|
||||
phase_data.energy_delivered / 1000000.0,
|
||||
phase_data.energy_received / 1000000.0,
|
||||
phase_data.active_power / 1000.0,
|
||||
phase_data.frequency,
|
||||
phase_data.voltage,
|
||||
phase_data.current,
|
||||
phase_data.power_factor,
|
||||
len(phase_data.status_flags),
|
||||
)
|
||||
for phase_data in mock_envoy.data.ctmeters_phases[cttype].values()
|
||||
]
|
||||
)
|
||||
|
||||
count_names: int = 0
|
||||
for name, target in list(
|
||||
zip(
|
||||
[
|
||||
entity.replace("<cttype>", cttype).replace("-", "_")
|
||||
for entity in CT_NAMES_FLOAT_PHASE
|
||||
],
|
||||
CT_NAMES_FLOAT_PHASE_TARGET,
|
||||
strict=False,
|
||||
)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert float(entity_state.state) == target
|
||||
count_names += 1
|
||||
|
||||
CT_NAMES_STR_PHASE_TARGET = [
|
||||
phase_data.metering_status
|
||||
for phase_data in mock_envoy.data.ctmeters_phases[cttype].values()
|
||||
]
|
||||
|
||||
for name, target in list(
|
||||
zip(
|
||||
[
|
||||
entity.replace("<cttype>", cttype).replace("-", "_")
|
||||
for entity in CT_NAMES_STR_PHASE
|
||||
],
|
||||
CT_NAMES_STR_PHASE_TARGET,
|
||||
strict=False,
|
||||
)
|
||||
):
|
||||
assert (entity_state := hass.states.get(f"{ENTITY_BASE}_{name}"))
|
||||
assert entity_state.state == target
|
||||
count_names += 1
|
||||
|
||||
# verify we're testing them all
|
||||
assert len(CT_NAMES_FLOAT_PHASE) + len(CT_NAMES_STR_PHASE) == count_names
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mock_envoy"),
|
||||
[
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from evohomeasync2 import EvohomeClient
|
||||
@@ -19,11 +18,10 @@ from homeassistant.components.evohome.const import (
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
async def test_refresh_system(
|
||||
async def test_service_refresh_system(
|
||||
hass: HomeAssistant,
|
||||
evohome: EvohomeClient,
|
||||
) -> None:
|
||||
@@ -42,7 +40,7 @@ async def test_refresh_system(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
async def test_reset_system(
|
||||
async def test_service_reset_system(
|
||||
hass: HomeAssistant,
|
||||
ctl_id: str,
|
||||
) -> None:
|
||||
@@ -61,7 +59,7 @@ async def test_reset_system(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
async def test_set_system_mode(
|
||||
async def test_ctl_set_system_mode(
|
||||
hass: HomeAssistant,
|
||||
ctl_id: str,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
@@ -117,7 +115,7 @@ async def test_set_system_mode(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
async def test_clear_zone_override(
|
||||
async def test_zone_clear_zone_override(
|
||||
hass: HomeAssistant,
|
||||
zone_id: str,
|
||||
) -> None:
|
||||
@@ -128,8 +126,9 @@ async def test_clear_zone_override(
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
EvoService.CLEAR_ZONE_OVERRIDE,
|
||||
{},
|
||||
target={ATTR_ENTITY_ID: zone_id},
|
||||
{
|
||||
ATTR_ENTITY_ID: zone_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -137,7 +136,7 @@ async def test_clear_zone_override(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
async def test_set_zone_override(
|
||||
async def test_zone_set_zone_override(
|
||||
hass: HomeAssistant,
|
||||
zone_id: str,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
@@ -152,9 +151,9 @@ async def test_set_zone_override(
|
||||
DOMAIN,
|
||||
EvoService.SET_ZONE_OVERRIDE,
|
||||
{
|
||||
ATTR_ENTITY_ID: zone_id,
|
||||
ATTR_SETPOINT: 19.5,
|
||||
},
|
||||
target={ATTR_ENTITY_ID: zone_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -166,41 +165,13 @@ async def test_set_zone_override(
|
||||
DOMAIN,
|
||||
EvoService.SET_ZONE_OVERRIDE,
|
||||
{
|
||||
ATTR_ENTITY_ID: zone_id,
|
||||
ATTR_SETPOINT: 19.5,
|
||||
ATTR_DURATION: {"minutes": 135},
|
||||
},
|
||||
target={ATTR_ENTITY_ID: zone_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_fcn.assert_awaited_once_with(
|
||||
19.5, until=datetime(2024, 7, 10, 14, 15, tzinfo=UTC)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("install", ["default"])
|
||||
@pytest.mark.parametrize(
|
||||
("service", "service_data"),
|
||||
[
|
||||
(EvoService.CLEAR_ZONE_OVERRIDE, {}),
|
||||
(EvoService.SET_ZONE_OVERRIDE, {ATTR_SETPOINT: 19.5}),
|
||||
],
|
||||
)
|
||||
async def test_zone_services_with_ctl_id(
|
||||
hass: HomeAssistant,
|
||||
ctl_id: str,
|
||||
service: EvoService,
|
||||
service_data: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test calling zone-only services with a non-zone entity_id fail."""
|
||||
|
||||
with pytest.raises(ServiceValidationError) as excinfo:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
service,
|
||||
service_data,
|
||||
target={ATTR_ENTITY_ID: ctl_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert excinfo.value.translation_key == "zone_only_service"
|
||||
|
||||
@@ -76,10 +76,6 @@ async def test_config_flow(hass: HomeAssistant, config_entry: MockConfigEntry) -
|
||||
"homeassistant.components.forked_daapd.ForkedDaapdAPI.get_request",
|
||||
autospec=True,
|
||||
) as mock_get_request,
|
||||
patch(
|
||||
"homeassistant.components.forked_daapd.async_setup_entry",
|
||||
return_value=True,
|
||||
),
|
||||
):
|
||||
mock_get_request.return_value = SAMPLE_CONFIG
|
||||
mock_test_connection.return_value = ["ok", "My Music on myhost"]
|
||||
@@ -233,16 +229,10 @@ async def test_config_flow_zeroconf_valid(hass: HomeAssistant) -> None:
|
||||
async def test_options_flow(hass: HomeAssistant, config_entry: MockConfigEntry) -> None:
|
||||
"""Test config flow options."""
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.forked_daapd.ForkedDaapdAPI.get_request",
|
||||
autospec=True,
|
||||
) as mock_get_request,
|
||||
patch(
|
||||
"homeassistant.components.forked_daapd.async_setup_entry",
|
||||
return_value=True,
|
||||
),
|
||||
):
|
||||
with patch(
|
||||
"homeassistant.components.forked_daapd.ForkedDaapdAPI.get_request",
|
||||
autospec=True,
|
||||
) as mock_get_request:
|
||||
mock_get_request.return_value = SAMPLE_CONFIG
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
|
||||
@@ -336,13 +336,7 @@ async def test_entity_migration(
|
||||
config_entry=config_entry_v1_1,
|
||||
)
|
||||
|
||||
with (
|
||||
patch("homeassistant.components.home_connect.PLATFORMS", platforms),
|
||||
patch(
|
||||
"homeassistant.components.home_connect.async_setup_entry",
|
||||
return_value=True,
|
||||
),
|
||||
):
|
||||
with patch("homeassistant.components.home_connect.PLATFORMS", platforms):
|
||||
await hass.config_entries.async_setup(config_entry_v1_1.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
@@ -370,12 +364,8 @@ async def test_config_entry_unique_id_migration(
|
||||
assert config_entry_v1_2.unique_id != "1234567890"
|
||||
assert config_entry_v1_2.minor_version == 2
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.home_connect.async_setup_entry",
|
||||
return_value=True,
|
||||
):
|
||||
await hass.config_entries.async_setup(config_entry_v1_2.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(config_entry_v1_2.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry_v1_2.unique_id == "1234567890"
|
||||
assert config_entry_v1_2.minor_version == 3
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""The tests for the Homematic notification platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
@@ -11,15 +9,11 @@ from tests.common import assert_setup_component
|
||||
|
||||
async def test_setup_full(hass: HomeAssistant) -> None:
|
||||
"""Test valid configuration."""
|
||||
with patch(
|
||||
"homeassistant.components.homematic.HMConnection",
|
||||
return_value=MagicMock(),
|
||||
):
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
with assert_setup_component(1, domain="notify") as handle_config:
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
@@ -41,15 +35,11 @@ async def test_setup_full(hass: HomeAssistant) -> None:
|
||||
|
||||
async def test_setup_without_optional(hass: HomeAssistant) -> None:
|
||||
"""Test valid configuration without optional."""
|
||||
with patch(
|
||||
"homeassistant.components.homematic.HMConnection",
|
||||
return_value=MagicMock(),
|
||||
):
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"homematic",
|
||||
{"homematic": {"hosts": {"ccu2": {"host": "127.0.0.1"}}}},
|
||||
)
|
||||
with assert_setup_component(1, domain="notify") as handle_config:
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
|
||||
@@ -136,7 +136,6 @@ def fixture_mock_config_entry() -> MockConfigEntry:
|
||||
async def fixture_mock_integration(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_device: MagicMock,
|
||||
) -> MockConfigEntry:
|
||||
"""Return a mock ConfigEntry setup for the integration."""
|
||||
with (
|
||||
|
||||
@@ -400,18 +400,14 @@ async def test_reconfigure(
|
||||
return_value={"scb:network": {"Hostname": "scb"}}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.kostal_plenticore.async_setup_entry",
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "1.1.1.1",
|
||||
"password": "test-password",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
"host": "1.1.1.1",
|
||||
"password": "test-password",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_apiclient_class.assert_called_once_with(ANY, "1.1.1.1")
|
||||
mock_apiclient.__aenter__.assert_called_once()
|
||||
|
||||
@@ -90,7 +90,6 @@ async def test_device_already_configured(
|
||||
async def test_user_step_fail_with_error(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
exception: Exception,
|
||||
expected_error: str,
|
||||
) -> None:
|
||||
@@ -125,7 +124,6 @@ async def test_user_step_fail_with_error(
|
||||
async def test_reconfigure(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test reconfigure flow."""
|
||||
@@ -155,7 +153,6 @@ async def test_reconfigure(
|
||||
async def test_reconfigure_fail_with_error(
|
||||
hass: HomeAssistant,
|
||||
mock_lunatone_info: AsyncMock,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
exception: Exception,
|
||||
expected_error: str,
|
||||
|
||||
@@ -46,6 +46,6 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
|
||||
@@ -20,7 +20,6 @@ from tests.common import MockConfigEntry, snapshot_platform
|
||||
async def test_binary_sensor_setup(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_madvr_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
|
||||
@@ -38,7 +38,6 @@ from tests.common import MockConfigEntry, snapshot_platform
|
||||
async def test_remote_setup(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_madvr_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
|
||||
@@ -9,9 +9,7 @@ import pytest
|
||||
@pytest.fixture
|
||||
def mock_simple_manager_fail():
|
||||
"""Mock datapoint Manager with default values for testing in config_flow."""
|
||||
with patch(
|
||||
"homeassistant.components.metoffice.config_flow.Manager"
|
||||
) as mock_manager:
|
||||
with patch("datapoint.Manager.Manager") as mock_manager:
|
||||
instance = mock_manager.return_value
|
||||
instance.get_forecast = APIException()
|
||||
instance.latitude = None
|
||||
|
||||
@@ -687,11 +687,10 @@ async def test_discovered_by_dhcp_updates_host(
|
||||
assert config_entry.data[CONF_HOST] == "1.2.3.4"
|
||||
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
|
||||
with patch("homeassistant.components.onvif.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_DHCP}, data=DHCP_DISCOVERY
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_DHCP}, data=DHCP_DISCOVERY
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
"""Test the Panasonic Viera config flow."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from panasonic_viera import SOAPError
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.panasonic_viera.const import (
|
||||
@@ -28,16 +26,6 @@ from .conftest import (
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Mock setting up a config entry."""
|
||||
with patch(
|
||||
"homeassistant.components.panasonic_viera.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup:
|
||||
yield mock_setup
|
||||
|
||||
|
||||
async def test_flow_non_encrypted(hass: HomeAssistant) -> None:
|
||||
"""Test flow without encryption."""
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'config_entry': dict({
|
||||
'data': dict({
|
||||
'api_token': '**REDACTED**',
|
||||
'url': '**REDACTED**',
|
||||
'url': 'https://127.0.0.1:9000/',
|
||||
'verify_ssl': True,
|
||||
}),
|
||||
'disabled_by': None,
|
||||
|
||||
@@ -122,12 +122,9 @@ async def test_unknown_error(hass: HomeAssistant) -> None:
|
||||
|
||||
async def test_zero_conf(hass: HomeAssistant) -> None:
|
||||
"""Test the manual flow for zero config."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.radarr.config_flow.RadarrClient.async_try_zeroconf",
|
||||
return_value=("v3", API_KEY, "/test"),
|
||||
),
|
||||
patch_async_setup_entry(),
|
||||
with patch(
|
||||
"homeassistant.components.radarr.config_flow.RadarrClient.async_try_zeroconf",
|
||||
return_value=("v3", API_KEY, "/test"),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
@@ -142,12 +139,9 @@ async def test_zero_conf(hass: HomeAssistant) -> None:
|
||||
|
||||
async def test_url_rewrite(hass: HomeAssistant) -> None:
|
||||
"""Test auth flow url rewrite."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.radarr.config_flow.RadarrClient.async_try_zeroconf",
|
||||
return_value=("v3", API_KEY, "/test"),
|
||||
),
|
||||
patch_async_setup_entry(),
|
||||
with patch(
|
||||
"homeassistant.components.radarr.config_flow.RadarrClient.async_try_zeroconf",
|
||||
return_value=("v3", API_KEY, "/test"),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
|
||||
@@ -62,12 +62,4 @@ MOCK_VEHICLES = {
|
||||
"pressure": "pressure.1.json",
|
||||
},
|
||||
},
|
||||
"megane_e_tech": {
|
||||
"endpoints": {
|
||||
"battery_status": "battery_status_charging.json",
|
||||
"cockpit": "cockpit_ev.json",
|
||||
"hvac_status": "hvac_status.1.json",
|
||||
"location": "location.json",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
{
|
||||
"accountId": "account-id-1",
|
||||
"country": "FR",
|
||||
"vehicleLinks": [
|
||||
{
|
||||
"brand": "RENAULT",
|
||||
"vin": "VF1MEGANEETECHVIN",
|
||||
"status": "ACTIVE",
|
||||
"linkType": "OWNER",
|
||||
"garageBrand": "renault",
|
||||
"startDate": "2024-01-16",
|
||||
"createdDate": "2024-01-16T13:31:27.089634Z",
|
||||
"lastModifiedDate": "2024-01-17T18:15:38.607328Z",
|
||||
"ownershipStartDate": "2024-01-16",
|
||||
"connectedDriver": {
|
||||
"role": "MAIN_DRIVER",
|
||||
"createdDate": "2024-01-17T18:15:38.607044265Z",
|
||||
"lastModifiedDate": "2024-01-17T18:15:38.607044265Z"
|
||||
},
|
||||
"vehicleDetails": {
|
||||
"vin": "VF1MEGANEETECHVIN",
|
||||
"registrationDate": "2024-01-16",
|
||||
"firstRegistrationDate": "2024-01-16",
|
||||
"engineType": "6AM",
|
||||
"engineRatio": "402",
|
||||
"modelSCR": "ZO1",
|
||||
"passToSalesDate": "2023-04-04",
|
||||
"deliveryCountry": {
|
||||
"code": "FR",
|
||||
"label": "FRANCE"
|
||||
},
|
||||
"family": {
|
||||
"code": "XCB",
|
||||
"label": "XCB FAMILY",
|
||||
"group": "007"
|
||||
},
|
||||
"tcu": {
|
||||
"code": "AIVCT",
|
||||
"label": "WITH AIVC CONNECTION UNIT",
|
||||
"group": "E70"
|
||||
},
|
||||
"battery": {
|
||||
"code": "BTBAE",
|
||||
"label": "BTBAE BATTERY",
|
||||
"group": "968"
|
||||
},
|
||||
"radioType": {
|
||||
"code": "NA448",
|
||||
"label": "IVI2 FULL PREM DAB",
|
||||
"group": "425"
|
||||
},
|
||||
"registrationCountry": {
|
||||
"code": "FR"
|
||||
},
|
||||
"brand": {
|
||||
"label": "RENAULT"
|
||||
},
|
||||
"model": {
|
||||
"code": "XCB1VE",
|
||||
"label": "MEGANE E-TECH",
|
||||
"group": "971"
|
||||
},
|
||||
"gearbox": {
|
||||
"code": "1EVGB",
|
||||
"label": "REDUCER FOR ELECTRIC MOTOR",
|
||||
"group": "427"
|
||||
},
|
||||
"version": {
|
||||
"code": "ICO2M J1 L"
|
||||
},
|
||||
"energy": {
|
||||
"code": "ELECX",
|
||||
"label": "ELECTRICITY",
|
||||
"group": "019"
|
||||
},
|
||||
"bodyType": {
|
||||
"code": "BCB",
|
||||
"label": "BERLINE FOR XCB",
|
||||
"group": "008"
|
||||
},
|
||||
"steeringSide": {
|
||||
"code": "LHDG",
|
||||
"label": "LEFT-HAND DRIVE",
|
||||
"group": "027"
|
||||
},
|
||||
"additionalEngineType": {
|
||||
"code": "NOATY",
|
||||
"label": "WITHOUT ADDITIONAL ENGINE TYPE",
|
||||
"group": "948"
|
||||
},
|
||||
"hybridation": {
|
||||
"code": "NOHYB",
|
||||
"label": "NO HYBRIDISATION LEVEL",
|
||||
"group": "956"
|
||||
},
|
||||
"registrationNumber": "REG-MEG-0",
|
||||
"vcd": "PAVEH/XCB/BCB/EA4/J1/ELECX/LHDG/TEMP/2WDRV/BEMBK/ACC02/00ABS/ACD03/STDRF/HTRWI/WFURP/CLK00/RVX07/1RVLG/FFGL2/SDLGT/RAL20/FSBAJ/SPADP/FAB02/NOCNV/LRSCO/LRS02/HAR04/RHR03/FSE06/RSE00/BIXPA/NTIBC/KMETR/TPRM2/SDSGL/NOSTK/SABG5/LEDCO/ESCHS/PALAW/SPBDA/M3CA3/PRROP/DB4C0/NOAGR/LRSW0/OSEWA/RVICM/TRSV0/NBRVX/FWL1T/RWL1T/NOOSW/REPKT/HTS02/00NLD/BRA03/AJSW2/HSTPL/SBR05/RMSB3/NA448/1EVGB/ASOC2/EVAU2/RIM09/TYSUM/ISOFI/EPER0/HR11M/SLCCA/NOATD/CPTC0/CHGS4/TL01A/BDPRO/NOADT/AIRBDE/PRUPTA/ELC1/NOETC/NOLSV/NOFEX/M2021/PHAS1/NOLTD/NOATY/NOHYB/60K0B/BTBAE/VEC151/XCB1VE/NB003/6AM/SFANT/ADR00/LKA05/PSFT0/BIHT0/NODUP/NOWAP/NOCCH/AMLT0/DRL02/RCALL/NOART/TBI00/MET05/BSD02/ECMD0/NRCAR/NOM2C/AIVCT/GSI00/TPNNP/TSGNE/2BCOL/ITP14/MDMOD/PXA00/NOPXB/PIG02/HTSW0/DAALT/WICH0/EV1GA1/SMOSP/NOWMC/FCOWA/C1AHS/NOPRA/VSPTA/1234Y/NOLIE/NOLII/NOWFI/AEB09/WOSRE/PRAHL/SPMIR/AVCAM/RAEB2/DTRNI",
|
||||
"manufacturingDate": "2023-04-04",
|
||||
"assets": [
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "mybrand_2",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "mybrand_2"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "mybrand_5",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_AV&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_AV&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "mybrand_5"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "myb_car_selector",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_AV&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=RSITE&bookmark=EXT_34_AV&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "myb_car_selector"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "myb_car_page_dashboard",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "myb_car_page_dashboard"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "myb_program_settings_page",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "myb_program_settings_page"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "myb_plug_and_charge_activation",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_RIGHT_SIDE&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_RIGHT_SIDE&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "myb_plug_and_charge_activation"
|
||||
},
|
||||
{
|
||||
"assetType": "PICTURE",
|
||||
"viewpoint": "myb_plug_and_charge_my_car",
|
||||
"renditions": [
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_SMALL",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_SMALL_V2"
|
||||
},
|
||||
{
|
||||
"resolutionType": "ONE_MYRENAULT_LARGE",
|
||||
"url": "https://3dv.renault.com/ImageFromBookmark?configuration=BCB%2FEA4%2FLHDG%2FACD03%2FSTDRF%2FWFURP%2FRVX07%2FRAL20%2FLRS02%2FFSE06%2FBIXPA%2FLEDCO%2FPALAW%2FSPBDA%2FLRSW0%2FRVICM%2FTRSV0%2FAJSW2%2FNA448%2FASOC2%2FRIM09%2FSLCCA%2FNOATD%2FCPTC0%2FBDPRO%2FAIRBDE%2FPRUPTA%2FNOETC%2FM2021%2FNB003%2FSFANT%2FPSFT0%2FNODUP%2FNOWAP%2FRCALL%2FBSD02%2F2BCOL%2FITP14%2FMDMOD%2FPXA00%2FNOPXB%2FPIG02%2FNOLII%2FAVCAM%2FDTRNI&databaseId=a7cc2a21-d3fe-43bf-8643-14d3b8f9b2fa&bookmarkSet=CARPICKER&bookmark=EXT_LEFT_SIDE&profile=HELIOS_OWNERSERVICES_LARGE"
|
||||
}
|
||||
],
|
||||
"viewPointInLowerCase": "myb_plug_and_charge_my_car"
|
||||
}
|
||||
],
|
||||
"yearsOfMaintenance": 12,
|
||||
"connectivityTechnology": "OPENRLINK",
|
||||
"easyConnectStore": true,
|
||||
"electrical": true,
|
||||
"deliveryDate": "2024-01-16",
|
||||
"retrievedFromDhs": false,
|
||||
"engineEnergyType": "ELEC",
|
||||
"radioCode": "",
|
||||
"premiumSubscribed": false,
|
||||
"batteryType": "NMC"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -495,155 +495,6 @@
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_charging-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_charging',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Charging',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Charging',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'vf1meganeetechvin_charging',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_charging-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'battery_charging',
|
||||
'friendly_name': 'REG-MEG-0 Charging',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_charging',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_hvac-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_hvac',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'HVAC',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'HVAC',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'hvac_status',
|
||||
'unique_id': 'vf1meganeetechvin_hvac_status',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_hvac-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 HVAC',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_hvac',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_plug-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_plug',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Plug',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.PLUG: 'plug'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Plug',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'vf1meganeetechvin_plugged_in',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[megane_e_tech][binary_sensor.reg_meg_0_plug-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'plug',
|
||||
'friendly_name': 'REG-MEG-0 Plug',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.reg_meg_0_plug',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensors[twingo_3_electric][binary_sensor.reg_twingo_iii_charging-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -1371,202 +1371,6 @@
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_flash_lights-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': None,
|
||||
'entity_id': 'button.reg_meg_0_flash_lights',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Flash lights',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Flash lights',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'flash_lights',
|
||||
'unique_id': 'vf1meganeetechvin_flash_lights',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_flash_lights-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 Flash lights',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.reg_meg_0_flash_lights',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_sound_horn-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': None,
|
||||
'entity_id': 'button.reg_meg_0_sound_horn',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Sound horn',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Sound horn',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'sound_horn',
|
||||
'unique_id': 'vf1meganeetechvin_sound_horn',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_sound_horn-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 Sound horn',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.reg_meg_0_sound_horn',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_start_air_conditioner-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': None,
|
||||
'entity_id': 'button.reg_meg_0_start_air_conditioner',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Start air conditioner',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Start air conditioner',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'start_air_conditioner',
|
||||
'unique_id': 'vf1meganeetechvin_start_air_conditioner',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_start_air_conditioner-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 Start air conditioner',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.reg_meg_0_start_air_conditioner',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_start_charge-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': None,
|
||||
'entity_id': 'button.reg_meg_0_start_charge',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Start charge',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Start charge',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'start_charge',
|
||||
'unique_id': 'vf1meganeetechvin_start_charge',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[megane_e_tech][button.reg_meg_0_start_charge-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 Start charge',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.reg_meg_0_start_charge',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_buttons[twingo_3_electric][button.reg_twingo_iii_flash_lights-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -204,59 +204,6 @@
|
||||
'state': 'not_home',
|
||||
})
|
||||
# ---
|
||||
# name: test_device_trackers[megane_e_tech][device_tracker.reg_meg_0_location-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'device_tracker',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'device_tracker.reg_meg_0_location',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Location',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Location',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'location',
|
||||
'unique_id': 'vf1meganeetechvin_location',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_device_trackers[megane_e_tech][device_tracker.reg_meg_0_location-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 Location',
|
||||
'gps_accuracy': 0,
|
||||
'latitude': 48.1234567,
|
||||
'longitude': 11.1234567,
|
||||
'source_type': <SourceType.GPS: 'gps'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'device_tracker.reg_meg_0_location',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'not_home',
|
||||
})
|
||||
# ---
|
||||
# name: test_device_trackers[twingo_3_electric][device_tracker.reg_twingo_iii_location-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -65,39 +65,6 @@
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_device_registry[megane_e_tech]
|
||||
list([
|
||||
DeviceRegistryEntrySnapshot({
|
||||
'area_id': None,
|
||||
'config_entries': <ANY>,
|
||||
'config_entries_subentries': <ANY>,
|
||||
'configuration_url': None,
|
||||
'connections': set({
|
||||
}),
|
||||
'disabled_by': None,
|
||||
'entry_type': None,
|
||||
'hw_version': None,
|
||||
'id': <ANY>,
|
||||
'identifiers': set({
|
||||
tuple(
|
||||
'renault',
|
||||
'VF1MEGANEETECHVIN',
|
||||
),
|
||||
}),
|
||||
'labels': set({
|
||||
}),
|
||||
'manufacturer': 'Renault',
|
||||
'model': 'Megane e-tech',
|
||||
'model_id': 'XCB1VE',
|
||||
'name': 'REG-MEG-0',
|
||||
'name_by_user': None,
|
||||
'primary_config_entry': <ANY>,
|
||||
'serial_number': None,
|
||||
'sw_version': None,
|
||||
'via_device_id': None,
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_device_registry[twingo_3_electric]
|
||||
list([
|
||||
DeviceRegistryEntrySnapshot({
|
||||
|
||||
@@ -2758,795 +2758,6 @@
|
||||
'state': 'plugged',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_admissible_charging_power-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_admissible_charging_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Admissible charging power',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Admissible charging power',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'admissible_charging_power',
|
||||
'unique_id': 'vf1meganeetechvin_charging_power',
|
||||
'unit_of_measurement': <UnitOfPower.KILO_WATT: 'kW'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_admissible_charging_power-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'power',
|
||||
'friendly_name': 'REG-MEG-0 Admissible charging power',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfPower.KILO_WATT: 'kW'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_admissible_charging_power',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '27.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_battery',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'vf1meganeetechvin_battery_level',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'battery',
|
||||
'friendly_name': 'REG-MEG-0 Battery',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_battery',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '60',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_autonomy-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_autonomy',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery autonomy',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.DISTANCE: 'distance'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery autonomy',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_autonomy',
|
||||
'unique_id': 'vf1meganeetechvin_battery_autonomy',
|
||||
'unit_of_measurement': <UnitOfLength.KILOMETERS: 'km'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_autonomy-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'distance',
|
||||
'friendly_name': 'REG-MEG-0 Battery autonomy',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfLength.KILOMETERS: 'km'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_autonomy',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '141',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_available_energy-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_available_energy',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery available energy',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery available energy',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_available_energy',
|
||||
'unique_id': 'vf1meganeetechvin_battery_available_energy',
|
||||
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_available_energy-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'energy',
|
||||
'friendly_name': 'REG-MEG-0 Battery available energy',
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_available_energy',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '31',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Battery temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery temperature',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_temperature',
|
||||
'unique_id': 'vf1meganeetechvin_battery_temperature',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_battery_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'REG-MEG-0 Battery temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_battery_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '20',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_charge_state-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'not_in_charge',
|
||||
'waiting_for_a_planned_charge',
|
||||
'charge_ended',
|
||||
'waiting_for_current_charge',
|
||||
'energy_flap_opened',
|
||||
'charge_in_progress',
|
||||
'charge_error',
|
||||
'unavailable',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_charge_state',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Charge state',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Charge state',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_state',
|
||||
'unique_id': 'vf1meganeetechvin_charge_state',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_charge_state-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'REG-MEG-0 Charge state',
|
||||
'options': list([
|
||||
'not_in_charge',
|
||||
'waiting_for_a_planned_charge',
|
||||
'charge_ended',
|
||||
'waiting_for_current_charge',
|
||||
'energy_flap_opened',
|
||||
'charge_in_progress',
|
||||
'charge_error',
|
||||
'unavailable',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_charge_state',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'charge_in_progress',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_charging_remaining_time-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_charging_remaining_time',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Charging remaining time',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Charging remaining time',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charging_remaining_time',
|
||||
'unique_id': 'vf1meganeetechvin_charging_remaining_time',
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_charging_remaining_time-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'duration',
|
||||
'friendly_name': 'REG-MEG-0 Charging remaining time',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTime.MINUTES: 'min'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_charging_remaining_time',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '145',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_hvac_soc_threshold-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_hvac_soc_threshold',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'HVAC SoC threshold',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'HVAC SoC threshold',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'hvac_soc_threshold',
|
||||
'unique_id': 'vf1meganeetechvin_hvac_soc_threshold',
|
||||
'unit_of_measurement': '%',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_hvac_soc_threshold-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'REG-MEG-0 HVAC SoC threshold',
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_hvac_soc_threshold',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_battery_activity-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_last_battery_activity',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Last battery activity',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last battery activity',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_last_activity',
|
||||
'unique_id': 'vf1meganeetechvin_battery_last_activity',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_battery_activity-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'REG-MEG-0 Last battery activity',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_last_battery_activity',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2020-01-12T21:40:16+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_hvac_activity-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_last_hvac_activity',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Last HVAC activity',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last HVAC activity',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'hvac_last_activity',
|
||||
'unique_id': 'vf1meganeetechvin_hvac_last_activity',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_hvac_activity-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'REG-MEG-0 Last HVAC activity',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_last_hvac_activity',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_location_activity-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_last_location_activity',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Last location activity',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Last location activity',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'location_last_activity',
|
||||
'unique_id': 'vf1meganeetechvin_location_last_activity',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_last_location_activity-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'timestamp',
|
||||
'friendly_name': 'REG-MEG-0 Last location activity',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_last_location_activity',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '2020-02-18T16:58:38+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_mileage-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_mileage',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Mileage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.DISTANCE: 'distance'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Mileage',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'mileage',
|
||||
'unique_id': 'vf1meganeetechvin_mileage',
|
||||
'unit_of_measurement': <UnitOfLength.KILOMETERS: 'km'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_mileage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'distance',
|
||||
'friendly_name': 'REG-MEG-0 Mileage',
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
'unit_of_measurement': <UnitOfLength.KILOMETERS: 'km'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_mileage',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '49114',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_outside_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_outside_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Outside temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Outside temperature',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'outside_temperature',
|
||||
'unique_id': 'vf1meganeetechvin_outside_temperature',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_outside_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'temperature',
|
||||
'friendly_name': 'REG-MEG-0 Outside temperature',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_outside_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '8.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_plug_state-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'unplugged',
|
||||
'plugged',
|
||||
'plugged_waiting_for_charge',
|
||||
'plug_error',
|
||||
'plug_unknown',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.reg_meg_0_plug_state',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Plug state',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Plug state',
|
||||
'platform': 'renault',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'plug_state',
|
||||
'unique_id': 'vf1meganeetechvin_plug_state',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[megane_e_tech][sensor.reg_meg_0_plug_state-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'REG-MEG-0 Plug state',
|
||||
'options': list([
|
||||
'unplugged',
|
||||
'plugged',
|
||||
'plugged_waiting_for_charge',
|
||||
'plug_error',
|
||||
'plug_unknown',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.reg_meg_0_plug_state',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'plugged',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[twingo_3_electric][sensor.reg_twingo_iii_admissible_charging_power-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -264,9 +264,7 @@ async def test_ssdp_discovery(
|
||||
|
||||
|
||||
async def test_options_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: None,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test options config flow."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
@@ -31,8 +31,7 @@ async def test_setup_success_no_region(hass: HomeAssistant) -> None:
|
||||
)
|
||||
mock_config.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.sharkiq.async_setup_entry", return_value=True):
|
||||
result = await async_setup_component(hass=hass, domain=DOMAIN, config={})
|
||||
result = await async_setup_component(hass=hass, domain=DOMAIN, config={})
|
||||
|
||||
assert result is True
|
||||
|
||||
|
||||
@@ -149,9 +149,7 @@ async def test_dhcp_discovery(
|
||||
|
||||
|
||||
async def test_dhcp_already_configured(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_setup_entry: AsyncMock,
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test starting a flow by dhcp when already configured."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
@@ -164,9 +162,7 @@ async def test_dhcp_already_configured(
|
||||
|
||||
|
||||
async def test_dhcp_already_configured_duplicate(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sma_client: MagicMock,
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test starting a flow by DHCP when already configured and MAC is added."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
@@ -284,7 +280,6 @@ async def test_full_flow_reauth(
|
||||
async def test_reauth_flow_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_setup_entry: AsyncMock,
|
||||
exception: Exception,
|
||||
error: str,
|
||||
) -> None:
|
||||
|
||||
@@ -10780,7 +10780,6 @@
|
||||
'after',
|
||||
'cleaning',
|
||||
'pause',
|
||||
'washing_mop',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
@@ -10829,7 +10828,6 @@
|
||||
'after',
|
||||
'cleaning',
|
||||
'pause',
|
||||
'washing_mop',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
@@ -11154,7 +11152,6 @@
|
||||
'after',
|
||||
'cleaning',
|
||||
'pause',
|
||||
'washing_mop',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
@@ -11203,7 +11200,6 @@
|
||||
'after',
|
||||
'cleaning',
|
||||
'pause',
|
||||
'washing_mop',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
|
||||
@@ -244,55 +244,6 @@
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_ks_hood_01001][switch.range_hood_do_not_disturb-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.range_hood_do_not_disturb',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Do not disturb',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Do not disturb',
|
||||
'platform': 'smartthings',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'do_not_disturb',
|
||||
'unique_id': 'fa5fca25-fa7a-1807-030a-2f72ee0f7bff_main_custom.doNotDisturbMode_doNotDisturb_doNotDisturb',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_ks_hood_01001][switch.range_hood_do_not_disturb-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Range hood Do not disturb',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.range_hood_do_not_disturb',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_ks_walloven_0107x][switch.four_sabbath_mode-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
@@ -1028,55 +979,6 @@
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_rvc_map_01011][switch.robot_vacuum_do_not_disturb-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.robot_vacuum_do_not_disturb',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Do not disturb',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Do not disturb',
|
||||
'platform': 'smartthings',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'do_not_disturb',
|
||||
'unique_id': '05accb39-2017-c98b-a5ab-04a81f4d3d9a_main_custom.doNotDisturbMode_doNotDisturb_doNotDisturb',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_rvc_map_01011][switch.robot_vacuum_do_not_disturb-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Robot vacuum Do not disturb',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.robot_vacuum_do_not_disturb',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_entities[da_rvc_normal_000001][switch.robot_vacuum-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
||||
@@ -7,16 +7,6 @@ import pytest
|
||||
from . import MOCK_SERVERS
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry():
|
||||
"""Mock setting up a config entry."""
|
||||
with patch(
|
||||
"homeassistant.components.speedtestdotnet.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup:
|
||||
yield mock_setup
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_api():
|
||||
"""Mock entry setup."""
|
||||
|
||||
@@ -14,7 +14,7 @@ from homeassistant.data_entry_flow import FlowResultType
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_flow_works(hass: HomeAssistant, mock_setup_entry: MagicMock) -> None:
|
||||
async def test_flow_works(hass: HomeAssistant) -> None:
|
||||
"""Test user config."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
|
||||
@@ -25,15 +25,12 @@ async def test_flow_user(hass: HomeAssistant) -> None:
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with (
|
||||
patch_config_flow_tautulli(AsyncMock()),
|
||||
patch("homeassistant.components.tautulli.async_setup_entry", return_value=True),
|
||||
):
|
||||
with patch_config_flow_tautulli(AsyncMock()):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_DATA,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == NAME
|
||||
@@ -51,15 +48,12 @@ async def test_flow_user_cannot_connect(hass: HomeAssistant) -> None:
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"]["base"] == "cannot_connect"
|
||||
|
||||
with (
|
||||
patch_config_flow_tautulli(AsyncMock()),
|
||||
patch("homeassistant.components.tautulli.async_setup_entry", return_value=True),
|
||||
):
|
||||
with patch_config_flow_tautulli(AsyncMock()):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_DATA,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == NAME
|
||||
@@ -77,15 +71,12 @@ async def test_flow_user_invalid_auth(hass: HomeAssistant) -> None:
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"]["base"] == "invalid_auth"
|
||||
|
||||
with (
|
||||
patch_config_flow_tautulli(AsyncMock()),
|
||||
patch("homeassistant.components.tautulli.async_setup_entry", return_value=True),
|
||||
):
|
||||
with patch_config_flow_tautulli(AsyncMock()):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_DATA,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == NAME
|
||||
@@ -103,15 +94,12 @@ async def test_flow_user_unknown_error(hass: HomeAssistant) -> None:
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"]["base"] == "unknown"
|
||||
|
||||
with (
|
||||
patch_config_flow_tautulli(AsyncMock()),
|
||||
patch("homeassistant.components.tautulli.async_setup_entry", return_value=True),
|
||||
):
|
||||
with patch_config_flow_tautulli(AsyncMock()):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=CONF_DATA,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == NAME
|
||||
@@ -150,15 +138,12 @@ async def test_flow_user_multiple_entries_allowed(hass: HomeAssistant) -> None:
|
||||
CONF_API_KEY: "efgh",
|
||||
CONF_VERIFY_SSL: True,
|
||||
}
|
||||
with (
|
||||
patch_config_flow_tautulli(AsyncMock()),
|
||||
patch("homeassistant.components.tautulli.async_setup_entry", return_value=True),
|
||||
):
|
||||
with patch_config_flow_tautulli(AsyncMock()):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=user_input,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result2["title"] == NAME
|
||||
|
||||
@@ -57,8 +57,6 @@ async def test_service_reconnect_client(
|
||||
|
||||
async def test_service_reconnect_failed_with_invalid_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_omada_site_client: MagicMock,
|
||||
mock_omada_client: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test reconnect with invalid config entry raises ServiceValidationError."""
|
||||
@@ -104,8 +102,6 @@ async def test_service_reconnect_without_config_entry_id(
|
||||
|
||||
async def test_service_reconnect_entry_not_loaded(
|
||||
hass: HomeAssistant,
|
||||
mock_omada_site_client: MagicMock,
|
||||
mock_omada_client: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test reconnect service raises error when entry is not loaded."""
|
||||
|
||||
@@ -30,7 +30,6 @@ from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
async def test_config_flow_entry_migrate_1_1_to_1_2(
|
||||
hass: HomeAssistant,
|
||||
mock_transmission_client: AsyncMock,
|
||||
) -> None:
|
||||
"""Test that config flow entry is migrated correctly from v1.1 to v1.2."""
|
||||
entry = MockConfigEntry(
|
||||
@@ -151,7 +150,6 @@ async def test_unload_entry(
|
||||
)
|
||||
async def test_migrate_unique_id(
|
||||
hass: HomeAssistant,
|
||||
mock_transmission_client: AsyncMock,
|
||||
entity_registry: er.EntityRegistry,
|
||||
domain: str,
|
||||
old_unique_id: str,
|
||||
|
||||
@@ -487,6 +487,80 @@ async def test_segments_changed_issue(
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_flow_fixture")
|
||||
@pytest.mark.parametrize("area_mapping", [{"area_1": ["seg_1"]}, {}])
|
||||
async def test_segments_mapping_not_configured_issue(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
area_mapping: dict[str, list[str]],
|
||||
) -> None:
|
||||
"""Test segments_mapping_not_configured issue."""
|
||||
mock_vacuum = MockVacuumWithCleanArea(name="Testing", entity_id="vacuum.testing")
|
||||
|
||||
config_entry = MockConfigEntry(domain="test")
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"test",
|
||||
async_setup_entry=help_async_setup_entry_init,
|
||||
async_unload_entry=help_async_unload_entry,
|
||||
),
|
||||
)
|
||||
setup_test_component_platform(hass, DOMAIN, [mock_vacuum], from_config_entry=True)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_entry = entity_registry.async_get(mock_vacuum.entity_id)
|
||||
|
||||
issue_id = f"segments_mapping_not_configured_{entity_entry.id}"
|
||||
issue = ir.async_get(hass).async_get_issue(DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_key == "segments_mapping_not_configured"
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
mock_vacuum.entity_id,
|
||||
DOMAIN,
|
||||
{
|
||||
"area_mapping": area_mapping,
|
||||
"last_seen_segments": [asdict(segment) for segment in mock_vacuum.segments],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config_flow_fixture")
|
||||
async def test_no_segments_mapping_issue_without_clean_area(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test no repair issue is created when CLEAN_AREA is not supported."""
|
||||
mock_vacuum = MockVacuum(name="Testing", entity_id="vacuum.testing")
|
||||
|
||||
config_entry = MockConfigEntry(domain="test")
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"test",
|
||||
async_setup_entry=help_async_setup_entry_init,
|
||||
async_unload_entry=help_async_unload_entry,
|
||||
),
|
||||
)
|
||||
setup_test_component_platform(hass, DOMAIN, [mock_vacuum], from_config_entry=True)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issues = ir.async_get(hass).issues
|
||||
assert not any(
|
||||
issue_id[1].startswith("segments_mapping_not_configured") for issue_id in issues
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("is_built_in", "log_warnings"), [(True, 0), (False, 3)])
|
||||
async def test_vacuum_log_deprecated_battery_using_properties(
|
||||
hass: HomeAssistant,
|
||||
|
||||
@@ -153,9 +153,12 @@ async def test_reboot_gateway_service_raises_on_exception(
|
||||
|
||||
|
||||
async def test_reboot_gateway_service_raises_validation_error(
|
||||
hass: HomeAssistant,
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test that reboot_gateway service raises ServiceValidationError when no gateway is loaded."""
|
||||
# Add the config entry but don't set it up
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
# Set up the velux integration's async_setup to register the service
|
||||
await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
@@ -159,10 +159,9 @@ async def test_full_ssdp_flow_implementation(hass: HomeAssistant) -> None:
|
||||
"components": "light",
|
||||
}
|
||||
|
||||
with patch("homeassistant.components.wilight.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == f"WL{WILIGHT_ID}"
|
||||
|
||||
@@ -83,19 +83,6 @@ def test_write_utf8_file_fails_at_rename_and_remove(
|
||||
assert "File replacement cleanup failed" in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("func", [write_utf8_file, write_utf8_file_atomic])
|
||||
def test_write_utf8_file_with_non_ascii_content(tmp_path: Path, func) -> None:
|
||||
"""Test files with non-ASCII content can be written even when locale is ASCII."""
|
||||
test_file = tmp_path / "test.json"
|
||||
non_ascii_data = '{"name":"自动化","emoji":"🏠"}'
|
||||
|
||||
with patch("locale.getpreferredencoding", return_value="ascii"):
|
||||
func(test_file, non_ascii_data, False)
|
||||
|
||||
file_text = test_file.read_text(encoding="utf-8")
|
||||
assert file_text == non_ascii_data
|
||||
|
||||
|
||||
def test_write_utf8_file_atomic_fails(tmpdir: py.path.local) -> None:
|
||||
"""Test OSError from write_utf8_file_atomic is rethrown as WriteError."""
|
||||
test_dir = tmpdir.mkdir("files")
|
||||
|
||||
Reference in New Issue
Block a user