Enable N806 (#171388)
Co-authored-by: Ariel Ebersberger <31776703+justanotherariel@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
0b687df9f8
commit
49c045236c
@@ -230,13 +230,13 @@ async def async_migrate_entry(hass: HomeAssistant, entry: AnthropicConfigEntry)
|
|||||||
|
|
||||||
if entry.version == 2 and entry.minor_version == 3:
|
if entry.version == 2 and entry.minor_version == 3:
|
||||||
# Remove Temperature parameter
|
# Remove Temperature parameter
|
||||||
CONF_TEMPERATURE = "temperature"
|
temperature_key = "temperature"
|
||||||
|
|
||||||
for subentry in entry.subentries.values():
|
for subentry in entry.subentries.values():
|
||||||
data = subentry.data.copy()
|
data = subentry.data.copy()
|
||||||
if CONF_TEMPERATURE not in data:
|
if temperature_key not in data:
|
||||||
continue
|
continue
|
||||||
data.pop(CONF_TEMPERATURE, None)
|
data.pop(temperature_key, None)
|
||||||
hass.config_entries.async_update_subentry(entry, subentry, data=data)
|
hass.config_entries.async_update_subentry(entry, subentry, data=data)
|
||||||
|
|
||||||
hass.config_entries.async_update_entry(entry, minor_version=4)
|
hass.config_entries.async_update_entry(entry, minor_version=4)
|
||||||
|
|||||||
@@ -49,6 +49,20 @@ SENSORS_TYPE_COUNT = "sensors_count"
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_ENTITY_MIGRATION_ID = {
|
||||||
|
"sensor_connected_device": "Devices Connected",
|
||||||
|
"sensor_rx_bytes": "Download",
|
||||||
|
"sensor_tx_bytes": "Upload",
|
||||||
|
"sensor_rx_rates": "Download Speed",
|
||||||
|
"sensor_tx_rates": "Upload Speed",
|
||||||
|
"sensor_load_avg1": "Load Avg (1m)",
|
||||||
|
"sensor_load_avg5": "Load Avg (5m)",
|
||||||
|
"sensor_load_avg15": "Load Avg (15m)",
|
||||||
|
"2.4GHz": "2.4GHz Temperature",
|
||||||
|
"5.0GHz": "5GHz Temperature",
|
||||||
|
"CPU": "CPU Temperature",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class AsusWrtSensorDataHandler:
|
class AsusWrtSensorDataHandler:
|
||||||
"""Data handler for AsusWrt sensor."""
|
"""Data handler for AsusWrt sensor."""
|
||||||
@@ -187,20 +201,6 @@ class AsusWrtRouter:
|
|||||||
|
|
||||||
def _migrate_entities_unique_id(self) -> None:
|
def _migrate_entities_unique_id(self) -> None:
|
||||||
"""Migrate router entities to new unique id format."""
|
"""Migrate router entities to new unique id format."""
|
||||||
_ENTITY_MIGRATION_ID = {
|
|
||||||
"sensor_connected_device": "Devices Connected",
|
|
||||||
"sensor_rx_bytes": "Download",
|
|
||||||
"sensor_tx_bytes": "Upload",
|
|
||||||
"sensor_rx_rates": "Download Speed",
|
|
||||||
"sensor_tx_rates": "Upload Speed",
|
|
||||||
"sensor_load_avg1": "Load Avg (1m)",
|
|
||||||
"sensor_load_avg5": "Load Avg (5m)",
|
|
||||||
"sensor_load_avg15": "Load Avg (15m)",
|
|
||||||
"2.4GHz": "2.4GHz Temperature",
|
|
||||||
"5.0GHz": "5GHz Temperature",
|
|
||||||
"CPU": "CPU Temperature",
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_reg = er.async_get(self.hass)
|
entity_reg = er.async_get(self.hass)
|
||||||
router_entries = er.async_entries_for_config_entry(
|
router_entries = er.async_entries_for_config_entry(
|
||||||
entity_reg, self._entry.entry_id
|
entity_reg, self._entry.entry_id
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class UKFloodsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
self.stations = {}
|
self.stations = {}
|
||||||
for station in stations:
|
for station in stations:
|
||||||
label = station["label"]
|
label = station["label"]
|
||||||
rloId = station["RLOIid"]
|
rlo_id = station["RLOIid"]
|
||||||
|
|
||||||
# API annoyingly sometimes returns a list and some times returns a string
|
# API annoyingly sometimes returns a list and some times returns a string
|
||||||
# E.g. L3121 has a label of ['Scurf Dyke', 'Scurf Dyke Dyke Level']
|
# E.g. L3121 has a label of ['Scurf Dyke', 'Scurf Dyke Dyke Level']
|
||||||
@@ -50,11 +50,11 @@ class UKFloodsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
# Similar for RLOIid
|
# Similar for RLOIid
|
||||||
# E.g. 0018 has an RLOIid of ['10427', '9154']
|
# E.g. 0018 has an RLOIid of ['10427', '9154']
|
||||||
if isinstance(rloId, list):
|
if isinstance(rlo_id, list):
|
||||||
rloId = rloId[-1]
|
rlo_id = rlo_id[-1]
|
||||||
|
|
||||||
fullName = label + " - " + rloId
|
full_name = label + " - " + rlo_id
|
||||||
self.stations[fullName] = station["stationReference"]
|
self.stations[full_name] = station["stationReference"]
|
||||||
|
|
||||||
if not self.stations:
|
if not self.stations:
|
||||||
return self.async_abort(reason="no_stations")
|
return self.async_abort(reason="no_stations")
|
||||||
|
|||||||
@@ -124,11 +124,11 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
for camera in coordinator.data:
|
for camera in coordinator.data:
|
||||||
device_category = coordinator.data[camera].get("device_category")
|
device_category = coordinator.data[camera].get("device_category")
|
||||||
supportExt = coordinator.data[camera].get("supportExt")
|
support_ext = coordinator.data[camera].get("supportExt")
|
||||||
if (
|
if (
|
||||||
device_category == DeviceCatagories.BATTERY_CAMERA_DEVICE_CATEGORY.value
|
device_category == DeviceCatagories.BATTERY_CAMERA_DEVICE_CATEGORY.value
|
||||||
and supportExt
|
and support_ext
|
||||||
and str(SupportExt.SupportBatteryManage.value) in supportExt
|
and str(SupportExt.SupportBatteryManage.value) in support_ext
|
||||||
):
|
):
|
||||||
entities.append(
|
entities.append(
|
||||||
EzvizSelect(coordinator, camera, BATTERY_WORK_MODE_SELECT_TYPE)
|
EzvizSelect(coordinator, camera, BATTERY_WORK_MODE_SELECT_TYPE)
|
||||||
|
|||||||
@@ -117,13 +117,13 @@ class DriveClient:
|
|||||||
"""Get storage quota of the current user."""
|
"""Get storage quota of the current user."""
|
||||||
res = await self._api.get_user(params={"fields": "storageQuota"})
|
res = await self._api.get_user(params={"fields": "storageQuota"})
|
||||||
|
|
||||||
storageQuota = res["storageQuota"]
|
storage_quota = res["storageQuota"]
|
||||||
limit = storageQuota.get("limit")
|
limit = storage_quota.get("limit")
|
||||||
return StorageQuotaData(
|
return StorageQuotaData(
|
||||||
limit=int(limit) if limit is not None else None,
|
limit=int(limit) if limit is not None else None,
|
||||||
usage=int(storageQuota.get("usage", 0)),
|
usage=int(storage_quota.get("usage", 0)),
|
||||||
usage_in_drive=int(storageQuota.get("usageInDrive", 0)),
|
usage_in_drive=int(storage_quota.get("usageInDrive", 0)),
|
||||||
usage_in_trash=int(storageQuota.get("usageInTrash", 0)),
|
usage_in_trash=int(storage_quota.get("usageInTrash", 0)),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_create_ha_root_folder_if_not_exists(self) -> tuple[str, str]:
|
async def async_create_ha_root_folder_if_not_exists(self) -> tuple[str, str]:
|
||||||
|
|||||||
@@ -580,17 +580,17 @@ class GoogleGenerativeAILLMBaseEntity(Entity):
|
|||||||
|
|
||||||
if tool_results:
|
if tool_results:
|
||||||
messages.append(_create_google_tool_response_content(tool_results))
|
messages.append(_create_google_tool_response_content(tool_results))
|
||||||
generateContentConfig = self.create_generate_content_config()
|
generate_content_config = self.create_generate_content_config()
|
||||||
generateContentConfig.tools = tools or None
|
generate_content_config.tools = tools or None
|
||||||
generateContentConfig.system_instruction = (
|
generate_content_config.system_instruction = (
|
||||||
prompt if supports_system_instruction else None
|
prompt if supports_system_instruction else None
|
||||||
)
|
)
|
||||||
generateContentConfig.automatic_function_calling = (
|
generate_content_config.automatic_function_calling = (
|
||||||
AutomaticFunctionCallingConfig(disable=True, maximum_remote_calls=None)
|
AutomaticFunctionCallingConfig(disable=True, maximum_remote_calls=None)
|
||||||
)
|
)
|
||||||
if structure:
|
if structure:
|
||||||
generateContentConfig.response_mime_type = "application/json"
|
generate_content_config.response_mime_type = "application/json"
|
||||||
generateContentConfig.response_schema = _format_schema(
|
generate_content_config.response_schema = _format_schema(
|
||||||
convert(
|
convert(
|
||||||
structure,
|
structure,
|
||||||
custom_serializer=(
|
custom_serializer=(
|
||||||
@@ -608,7 +608,7 @@ class GoogleGenerativeAILLMBaseEntity(Entity):
|
|||||||
*messages,
|
*messages,
|
||||||
]
|
]
|
||||||
chat = self._genai_client.aio.chats.create(
|
chat = self._genai_client.aio.chats.create(
|
||||||
model=model_name, history=messages, config=generateContentConfig
|
model=model_name, history=messages, config=generate_content_config
|
||||||
)
|
)
|
||||||
user_message = chat_log.content[-1]
|
user_message = chat_log.content[-1]
|
||||||
assert isinstance(user_message, conversation.UserContent)
|
assert isinstance(user_message, conversation.UserContent)
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ async def _manage_quests(call: ServiceCall) -> ServiceResponse:
|
|||||||
)
|
)
|
||||||
coordinator = entry.runtime_data
|
coordinator = entry.runtime_data
|
||||||
|
|
||||||
FUNC_MAP = {
|
func_map = {
|
||||||
SERVICE_ABORT_QUEST: coordinator.habitica.abort_quest,
|
SERVICE_ABORT_QUEST: coordinator.habitica.abort_quest,
|
||||||
SERVICE_ACCEPT_QUEST: coordinator.habitica.accept_quest,
|
SERVICE_ACCEPT_QUEST: coordinator.habitica.accept_quest,
|
||||||
SERVICE_CANCEL_QUEST: coordinator.habitica.cancel_quest,
|
SERVICE_CANCEL_QUEST: coordinator.habitica.cancel_quest,
|
||||||
@@ -322,7 +322,7 @@ async def _manage_quests(call: ServiceCall) -> ServiceResponse:
|
|||||||
SERVICE_START_QUEST: coordinator.habitica.start_quest,
|
SERVICE_START_QUEST: coordinator.habitica.start_quest,
|
||||||
}
|
}
|
||||||
|
|
||||||
func = FUNC_MAP[call.service]
|
func = func_map[call.service]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await func()
|
response = await func()
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ OPEN_CLOSE_ATTRIBUTES = [
|
|||||||
AttributeType.UP_DOWN,
|
AttributeType.UP_DOWN,
|
||||||
]
|
]
|
||||||
POSITION_ATTRIBUTES = [AttributeType.POSITION, AttributeType.SHUTTER_SLAT_POSITION]
|
POSITION_ATTRIBUTES = [AttributeType.POSITION, AttributeType.SHUTTER_SLAT_POSITION]
|
||||||
|
COVER_DEVICE_PROFILES = {
|
||||||
|
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
|
||||||
|
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
|
||||||
|
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_open_close_attribute(node: HomeeNode) -> HomeeAttribute | None:
|
def get_open_close_attribute(node: HomeeNode) -> HomeeAttribute | None:
|
||||||
@@ -69,12 +74,6 @@ def get_cover_features(
|
|||||||
|
|
||||||
def get_device_class(node: HomeeNode) -> CoverDeviceClass | None:
|
def get_device_class(node: HomeeNode) -> CoverDeviceClass | None:
|
||||||
"""Determine the device class a homee node based on the node profile."""
|
"""Determine the device class a homee node based on the node profile."""
|
||||||
COVER_DEVICE_PROFILES = {
|
|
||||||
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
|
|
||||||
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
|
|
||||||
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
|
|
||||||
}
|
|
||||||
|
|
||||||
return COVER_DEVICE_PROFILES.get(node.profile)
|
return COVER_DEVICE_PROFILES.get(node.profile)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ def log_rate_limits(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Output rate limit log line at given level."""
|
"""Output rate limit log line at given level."""
|
||||||
rate_limits = resp["rateLimits"]
|
rate_limits = resp["rateLimits"]
|
||||||
resetsAt = dt_util.parse_datetime(rate_limits["resetsAt"])
|
resets_at = dt_util.parse_datetime(rate_limits["resetsAt"])
|
||||||
resetsAtTime = resetsAt - dt_util.utcnow() if resetsAt is not None else "---"
|
resets_at_time = resets_at - dt_util.utcnow() if resets_at is not None else "---"
|
||||||
rate_limit_msg = (
|
rate_limit_msg = (
|
||||||
"iOS push notification rate limits for %s: "
|
"iOS push notification rate limits for %s: "
|
||||||
"%d sent, %d allowed, %d errors, "
|
"%d sent, %d allowed, %d errors, "
|
||||||
@@ -44,7 +44,7 @@ def log_rate_limits(
|
|||||||
rate_limits["successful"],
|
rate_limits["successful"],
|
||||||
rate_limits["maximum"],
|
rate_limits["maximum"],
|
||||||
rate_limits["errors"],
|
rate_limits["errors"],
|
||||||
str(resetsAtTime).split(".", maxsplit=1)[0],
|
str(resets_at_time).split(".", maxsplit=1)[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ async def async_handle_unload(coordinator: MadVRCoordinator) -> None:
|
|||||||
async def async_setup_entry(hass: HomeAssistant, entry: MadVRConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: MadVRConfigEntry) -> bool:
|
||||||
"""Set up the integration from a config entry."""
|
"""Set up the integration from a config entry."""
|
||||||
assert entry.unique_id
|
assert entry.unique_id
|
||||||
madVRClient = Madvr(
|
mad_vr_client = Madvr(
|
||||||
host=entry.data[CONF_HOST],
|
host=entry.data[CONF_HOST],
|
||||||
logger=_LOGGER,
|
logger=_LOGGER,
|
||||||
port=entry.data[CONF_PORT],
|
port=entry.data[CONF_PORT],
|
||||||
@@ -35,7 +35,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: MadVRConfigEntry) -> boo
|
|||||||
connect_timeout=10,
|
connect_timeout=10,
|
||||||
loop=hass.loop,
|
loop=hass.loop,
|
||||||
)
|
)
|
||||||
coordinator = MadVRCoordinator(hass, entry, madVRClient)
|
coordinator = MadVRCoordinator(hass, entry, mad_vr_client)
|
||||||
|
|
||||||
entry.runtime_data = coordinator
|
entry.runtime_data = coordinator
|
||||||
|
|
||||||
|
|||||||
@@ -84,12 +84,12 @@ class MBCover(MicroBeesEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open the cover."""
|
"""Open the cover."""
|
||||||
sendCommand = await self.coordinator.microbees.sendCommand(
|
send_command = await self.coordinator.microbees.sendCommand(
|
||||||
self.actuator_up_id,
|
self.actuator_up_id,
|
||||||
self.actuator_up.configuration.actuator_timing * 1000,
|
self.actuator_up.configuration.actuator_timing * 1000,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not sendCommand:
|
if not send_command:
|
||||||
raise HomeAssistantError(f"Failed to open {self.name}")
|
raise HomeAssistantError(f"Failed to open {self.name}")
|
||||||
|
|
||||||
self._attr_is_opening = True
|
self._attr_is_opening = True
|
||||||
@@ -101,11 +101,11 @@ class MBCover(MicroBeesEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close the cover."""
|
"""Close the cover."""
|
||||||
sendCommand = await self.coordinator.microbees.sendCommand(
|
send_command = await self.coordinator.microbees.sendCommand(
|
||||||
self.actuator_down_id,
|
self.actuator_down_id,
|
||||||
self.actuator_down.configuration.actuator_timing * 1000,
|
self.actuator_down.configuration.actuator_timing * 1000,
|
||||||
)
|
)
|
||||||
if not sendCommand:
|
if not send_command:
|
||||||
raise HomeAssistantError(f"Failed to close {self.name}")
|
raise HomeAssistantError(f"Failed to close {self.name}")
|
||||||
|
|
||||||
self._attr_is_closing = True
|
self._attr_is_closing = True
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ class MBLight(MicroBeesActuatorEntity, LightEntity):
|
|||||||
"""Turn on the light."""
|
"""Turn on the light."""
|
||||||
if ATTR_RGBW_COLOR in kwargs:
|
if ATTR_RGBW_COLOR in kwargs:
|
||||||
self._attr_rgbw_color = kwargs[ATTR_RGBW_COLOR]
|
self._attr_rgbw_color = kwargs[ATTR_RGBW_COLOR]
|
||||||
sendCommand = await self.coordinator.microbees.sendCommand(
|
send_command = await self.coordinator.microbees.sendCommand(
|
||||||
self.actuator_id, 1, color=self._attr_rgbw_color
|
self.actuator_id, 1, color=self._attr_rgbw_color
|
||||||
)
|
)
|
||||||
if not sendCommand:
|
if not send_command:
|
||||||
raise HomeAssistantError(f"Failed to turn on {self.name}")
|
raise HomeAssistantError(f"Failed to turn on {self.name}")
|
||||||
|
|
||||||
self.actuator.value = True
|
self.actuator.value = True
|
||||||
@@ -67,10 +67,10 @@ class MBLight(MicroBeesActuatorEntity, LightEntity):
|
|||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn off the light."""
|
"""Turn off the light."""
|
||||||
sendCommand = await self.coordinator.microbees.sendCommand(
|
send_command = await self.coordinator.microbees.sendCommand(
|
||||||
self.actuator_id, 0, color=self._attr_rgbw_color
|
self.actuator_id, 0, color=self._attr_rgbw_color
|
||||||
)
|
)
|
||||||
if not sendCommand:
|
if not send_command:
|
||||||
raise HomeAssistantError(f"Failed to turn off {self.name}")
|
raise HomeAssistantError(f"Failed to turn off {self.name}")
|
||||||
|
|
||||||
self.actuator.value = False
|
self.actuator.value = False
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ def log_rate_limits(device_name, resp, level=logging.INFO):
|
|||||||
return
|
return
|
||||||
|
|
||||||
rate_limits = resp[ATTR_PUSH_RATE_LIMITS]
|
rate_limits = resp[ATTR_PUSH_RATE_LIMITS]
|
||||||
resetsAt = rate_limits[ATTR_PUSH_RATE_LIMITS_RESETS_AT]
|
resets_at = rate_limits[ATTR_PUSH_RATE_LIMITS_RESETS_AT]
|
||||||
resetsAtTime = dt_util.parse_datetime(resetsAt) - dt_util.utcnow()
|
resets_at_time = dt_util.parse_datetime(resets_at) - dt_util.utcnow()
|
||||||
rate_limit_msg = (
|
rate_limit_msg = (
|
||||||
"mobile_app push notification rate limits for %s: "
|
"mobile_app push notification rate limits for %s: "
|
||||||
"%d sent, %d allowed, %d errors, "
|
"%d sent, %d allowed, %d errors, "
|
||||||
@@ -166,7 +166,7 @@ def log_rate_limits(device_name, resp, level=logging.INFO):
|
|||||||
rate_limits[ATTR_PUSH_RATE_LIMITS_SUCCESSFUL],
|
rate_limits[ATTR_PUSH_RATE_LIMITS_SUCCESSFUL],
|
||||||
rate_limits[ATTR_PUSH_RATE_LIMITS_MAXIMUM],
|
rate_limits[ATTR_PUSH_RATE_LIMITS_MAXIMUM],
|
||||||
rate_limits[ATTR_PUSH_RATE_LIMITS_ERRORS],
|
rate_limits[ATTR_PUSH_RATE_LIMITS_ERRORS],
|
||||||
str(resetsAtTime).split(".", maxsplit=1)[0],
|
str(resets_at_time).split(".", maxsplit=1)[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -146,14 +146,14 @@ async def determine_api_version(
|
|||||||
debugging.
|
debugging.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
holeV6 = api_by_version(hass, entry, 6, password="wrong_password")
|
hole_v6 = api_by_version(hass, entry, 6, password="wrong_password")
|
||||||
try:
|
try:
|
||||||
await holeV6.authenticate()
|
await hole_v6.authenticate()
|
||||||
except HoleConnectionError as err:
|
except HoleConnectionError as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Unexpected error connecting to Pi-hole v6 API"
|
"Unexpected error connecting to Pi-hole v6 API"
|
||||||
" at %s: %s. Trying version 5 API",
|
" at %s: %s. Trying version 5 API",
|
||||||
holeV6.base_url,
|
hole_v6.base_url,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
# Ideally python-hole would raise a specific exception for authentication failures
|
# Ideally python-hole would raise a specific exception for authentication failures
|
||||||
@@ -161,12 +161,12 @@ async def determine_api_version(
|
|||||||
if str(ex_v6) == "Authentication failed: Invalid password":
|
if str(ex_v6) == "Authentication failed: Invalid password":
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Success connecting to Pi-hole at %s without auth, API version is : %s",
|
"Success connecting to Pi-hole at %s without auth, API version is : %s",
|
||||||
holeV6.base_url,
|
hole_v6.base_url,
|
||||||
6,
|
6,
|
||||||
)
|
)
|
||||||
return 6
|
return 6
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Connection to %s failed: %s, trying API version 5", holeV6.base_url, ex_v6
|
"Connection to %s failed: %s, trying API version 5", hole_v6.base_url, ex_v6
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# It seems that occasionally the auth can succeed
|
# It seems that occasionally the auth can succeed
|
||||||
@@ -175,34 +175,34 @@ async def determine_api_version(
|
|||||||
"Authenticated with %s through v6 API, but"
|
"Authenticated with %s through v6 API, but"
|
||||||
" succeeded with an incorrect password."
|
" succeeded with an incorrect password."
|
||||||
" This is a known bug",
|
" This is a known bug",
|
||||||
holeV6.base_url,
|
hole_v6.base_url,
|
||||||
)
|
)
|
||||||
return 6
|
return 6
|
||||||
holeV5 = api_by_version(hass, entry, 5, password="wrong_token")
|
hole_v5 = api_by_version(hass, entry, 5, password="wrong_token")
|
||||||
try:
|
try:
|
||||||
await holeV5.get_data()
|
await hole_v5.get_data()
|
||||||
|
|
||||||
except HoleConnectionError as err:
|
except HoleConnectionError as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Failed to connect to Pi-hole v5 API at %s: %s", holeV5.base_url, err
|
"Failed to connect to Pi-hole v5 API at %s: %s", hole_v5.base_url, err
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# V5 API returns [] to unauthenticated requests
|
# V5 API returns [] to unauthenticated requests
|
||||||
if not holeV5.data:
|
if not hole_v5.data:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Response '[]' from API without auth,"
|
"Response '[]' from API without auth,"
|
||||||
" pihole API version 5 probably"
|
" pihole API version 5 probably"
|
||||||
" detected at %s",
|
" detected at %s",
|
||||||
holeV5.base_url,
|
hole_v5.base_url,
|
||||||
)
|
)
|
||||||
return 5
|
return 5
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Unexpected response from Pi-hole API at %s: %s",
|
"Unexpected response from Pi-hole API at %s: %s",
|
||||||
holeV5.base_url,
|
hole_v5.base_url,
|
||||||
str(holeV5.data),
|
str(hole_v5.data),
|
||||||
)
|
)
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Could not determine pi-hole API version at: %s",
|
"Could not determine pi-hole API version at: %s",
|
||||||
holeV6.base_url,
|
hole_v6.base_url,
|
||||||
)
|
)
|
||||||
raise HoleError("Could not determine Pi-hole API version")
|
raise HoleError("Could not determine Pi-hole API version")
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ async def async_get_config_entry_diagnostics(
|
|||||||
host = reolink_data.host
|
host = reolink_data.host
|
||||||
api = host.api
|
api = host.api
|
||||||
|
|
||||||
IPC_cam: dict[int, dict[str, Any]] = {}
|
ipc_cam: dict[int, dict[str, Any]] = {}
|
||||||
for ch in api.channels:
|
for ch in api.channels:
|
||||||
IPC_cam[ch] = {}
|
ipc_cam[ch] = {}
|
||||||
IPC_cam[ch]["model"] = api.camera_model(ch)
|
ipc_cam[ch]["model"] = api.camera_model(ch)
|
||||||
IPC_cam[ch]["hardware version"] = api.camera_hardware_version(ch)
|
ipc_cam[ch]["hardware version"] = api.camera_hardware_version(ch)
|
||||||
IPC_cam[ch]["firmware version"] = api.camera_sw_version(ch)
|
ipc_cam[ch]["firmware version"] = api.camera_sw_version(ch)
|
||||||
IPC_cam[ch]["encoding main"] = await api.get_encoding(ch)
|
ipc_cam[ch]["encoding main"] = await api.get_encoding(ch)
|
||||||
if (signal := api.wifi_signal(ch)) is not None and api.wifi_connection(ch):
|
if (signal := api.wifi_signal(ch)) is not None and api.wifi_connection(ch):
|
||||||
IPC_cam[ch]["WiFi signal"] = signal
|
ipc_cam[ch]["WiFi signal"] = signal
|
||||||
|
|
||||||
chimes: dict[int, dict[str, Any]] = {}
|
chimes: dict[int, dict[str, Any]] = {}
|
||||||
for chime in api.chime_list:
|
for chime in api.chime_list:
|
||||||
@@ -50,7 +50,7 @@ async def async_get_config_entry_diagnostics(
|
|||||||
"stream protocol": api.protocol,
|
"stream protocol": api.protocol,
|
||||||
"channels": api.channels,
|
"channels": api.channels,
|
||||||
"stream channels": api.stream_channels,
|
"stream channels": api.stream_channels,
|
||||||
"IPC cams": IPC_cam,
|
"IPC cams": ipc_cam,
|
||||||
"Chimes": chimes,
|
"Chimes": chimes,
|
||||||
"capabilities": api.capabilities,
|
"capabilities": api.capabilities,
|
||||||
"cmd list": host.update_cmd,
|
"cmd list": host.update_cmd,
|
||||||
|
|||||||
@@ -47,21 +47,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: SolarlogConfigEntry) ->
|
|||||||
|
|
||||||
basic_coordinator = SolarLogBasicDataCoordinator(hass, entry, solarlog)
|
basic_coordinator = SolarLogBasicDataCoordinator(hass, entry, solarlog)
|
||||||
|
|
||||||
solarLogData = SolarlogIntegrationData(
|
solar_log_data = SolarlogIntegrationData(
|
||||||
api=solarlog,
|
api=solarlog,
|
||||||
basic_data_coordinator=basic_coordinator,
|
basic_data_coordinator=basic_coordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
await basic_coordinator.async_config_entry_first_refresh()
|
await basic_coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
entry.runtime_data = solarLogData
|
entry.runtime_data = solar_log_data
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Basic coordinator setup successful, extended data available: %s",
|
"Basic coordinator setup successful, extended data available: %s",
|
||||||
solarLogData.api.extended_data,
|
solar_log_data.api.extended_data,
|
||||||
)
|
)
|
||||||
|
|
||||||
if solarLogData.api.extended_data:
|
if solar_log_data.api.extended_data:
|
||||||
timeout = entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT)
|
timeout = entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT)
|
||||||
|
|
||||||
_LOGGER.debug("Setup of LongtimeDataCoordinator, saved timeout is %s", timeout)
|
_LOGGER.debug("Setup of LongtimeDataCoordinator, saved timeout is %s", timeout)
|
||||||
|
|||||||
@@ -335,40 +335,43 @@ async def async_setup_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Add solarlog entry."""
|
"""Add solarlog entry."""
|
||||||
|
|
||||||
solarLogIntegrationData: SolarlogIntegrationData = entry.runtime_data
|
solar_log_integration_data: SolarlogIntegrationData = entry.runtime_data
|
||||||
|
|
||||||
entities: list[SensorEntity] = [
|
entities: list[SensorEntity] = [
|
||||||
SolarLogBasicCoordinatorSensor(
|
SolarLogBasicCoordinatorSensor(
|
||||||
solarLogIntegrationData.basic_data_coordinator, sensor
|
solar_log_integration_data.basic_data_coordinator, sensor
|
||||||
)
|
)
|
||||||
for sensor in SOLARLOG_BASIC_SENSOR_TYPES
|
for sensor in SOLARLOG_BASIC_SENSOR_TYPES
|
||||||
]
|
]
|
||||||
|
|
||||||
if solarLogIntegrationData.longtime_data_coordinator is not None:
|
if solar_log_integration_data.longtime_data_coordinator is not None:
|
||||||
entities.extend(
|
entities.extend(
|
||||||
SolarLogLongtimeCoordinatorSensor(
|
SolarLogLongtimeCoordinatorSensor(
|
||||||
solarLogIntegrationData.longtime_data_coordinator, sensor
|
solar_log_integration_data.longtime_data_coordinator, sensor
|
||||||
)
|
)
|
||||||
for sensor in SOLARLOG_LONGTIME_SENSOR_TYPES
|
for sensor in SOLARLOG_LONGTIME_SENSOR_TYPES
|
||||||
)
|
)
|
||||||
|
|
||||||
# add battery sensors only if respective data is
|
# add battery sensors only if respective data is
|
||||||
# available (otherwise no battery attached to solarlog)
|
# available (otherwise no battery attached to solarlog)
|
||||||
if solarLogIntegrationData.basic_data_coordinator.data.battery_data is not None:
|
if (
|
||||||
|
solar_log_integration_data.basic_data_coordinator.data.battery_data
|
||||||
|
is not None
|
||||||
|
):
|
||||||
entities.extend(
|
entities.extend(
|
||||||
SolarLogBatterySensor(
|
SolarLogBatterySensor(
|
||||||
solarLogIntegrationData.basic_data_coordinator, sensor
|
solar_log_integration_data.basic_data_coordinator, sensor
|
||||||
)
|
)
|
||||||
for sensor in SOLARLOG_BATTERY_SENSOR_TYPES
|
for sensor in SOLARLOG_BATTERY_SENSOR_TYPES
|
||||||
)
|
)
|
||||||
|
|
||||||
if solarLogIntegrationData.device_data_coordinator is not None:
|
if solar_log_integration_data.device_data_coordinator is not None:
|
||||||
device_data = solarLogIntegrationData.device_data_coordinator.data
|
device_data = solar_log_integration_data.device_data_coordinator.data
|
||||||
|
|
||||||
if device_data:
|
if device_data:
|
||||||
entities.extend(
|
entities.extend(
|
||||||
SolarLogInverterSensor(
|
SolarLogInverterSensor(
|
||||||
solarLogIntegrationData.device_data_coordinator,
|
solar_log_integration_data.device_data_coordinator,
|
||||||
sensor,
|
sensor,
|
||||||
device_id,
|
device_id,
|
||||||
)
|
)
|
||||||
@@ -379,15 +382,15 @@ async def async_setup_entry(
|
|||||||
def _async_add_new_device(device_id: int) -> None:
|
def _async_add_new_device(device_id: int) -> None:
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
SolarLogInverterSensor(
|
SolarLogInverterSensor(
|
||||||
solarLogIntegrationData.device_data_coordinator,
|
solar_log_integration_data.device_data_coordinator,
|
||||||
sensor,
|
sensor,
|
||||||
device_id,
|
device_id,
|
||||||
)
|
)
|
||||||
for sensor in SOLARLOG_INVERTER_SENSOR_TYPES
|
for sensor in SOLARLOG_INVERTER_SENSOR_TYPES
|
||||||
if solarLogIntegrationData.device_data_coordinator is not None
|
if solar_log_integration_data.device_data_coordinator is not None
|
||||||
)
|
)
|
||||||
|
|
||||||
solarLogIntegrationData.device_data_coordinator.new_device_callbacks.append(
|
solar_log_integration_data.device_data_coordinator.new_device_callbacks.append(
|
||||||
_async_add_new_device
|
_async_add_new_device
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ async def make_new_device_data(
|
|||||||
manageable_by_webhook=default_config.webhook,
|
manageable_by_webhook=default_config.webhook,
|
||||||
)
|
)
|
||||||
|
|
||||||
_PLATFORM_LIST_MAP: dict[Platform, list] = {
|
_platform_list_map: dict[Platform, list] = {
|
||||||
Platform.BINARY_SENSOR: devices_data.binary_sensors,
|
Platform.BINARY_SENSOR: devices_data.binary_sensors,
|
||||||
Platform.BUTTON: devices_data.buttons,
|
Platform.BUTTON: devices_data.buttons,
|
||||||
Platform.CLIMATE: devices_data.climates,
|
Platform.CLIMATE: devices_data.climates,
|
||||||
@@ -342,7 +342,7 @@ async def make_new_device_data(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for platform in default_config.entity_config:
|
for platform in default_config.entity_config:
|
||||||
target_list = _PLATFORM_LIST_MAP.get(platform)
|
target_list = _platform_list_map.get(platform)
|
||||||
if target_list is None:
|
if target_list is None:
|
||||||
continue
|
continue
|
||||||
existing_ids = {item[0].device_id for item in target_list}
|
existing_ids = {item[0].device_id for item in target_list}
|
||||||
@@ -502,14 +502,14 @@ def _create_handle_webhook(
|
|||||||
_LOGGER.debug("Received invalid data from switchbot webhook %s", repr(data))
|
_LOGGER.debug("Received invalid data from switchbot webhook %s", repr(data))
|
||||||
return
|
return
|
||||||
_LOGGER.debug("Received data from switchbot webhook: %s", repr(data))
|
_LOGGER.debug("Received data from switchbot webhook: %s", repr(data))
|
||||||
deviceMac = data["context"]["deviceMac"]
|
device_mac = data["context"]["deviceMac"]
|
||||||
|
|
||||||
if deviceMac not in coordinators_by_id:
|
if device_mac not in coordinators_by_id:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Received data for unknown entity from switchbot webhook: %s", data
|
"Received data for unknown entity from switchbot webhook: %s", data
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
coordinators_by_id[deviceMac].async_set_updated_data(data["context"])
|
coordinators_by_id[device_mac].async_set_updated_data(data["context"])
|
||||||
|
|
||||||
return _internal_handle_webhook
|
return _internal_handle_webhook
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ MODEL_TO_CLASS_MAP = {
|
|||||||
MODEL_FAN_ZA5: FanZA5,
|
MODEL_FAN_ZA5: FanZA5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# List of models requiring specific lazy_discover setting
|
||||||
|
LAZY_DISCOVER_FOR_MODEL = {
|
||||||
|
"zhimi.fan.za3": True,
|
||||||
|
"zhimi.fan.za5": True,
|
||||||
|
"zhimi.airpurifier.za1": True,
|
||||||
|
"dmaker.fan.1c": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up the component."""
|
"""Set up the component."""
|
||||||
@@ -307,13 +315,6 @@ async def async_create_miio_device_and_coordinator(
|
|||||||
update_method = _async_update_data_default
|
update_method = _async_update_data_default
|
||||||
coordinator_class: type[DataUpdateCoordinator[Any]] = DataUpdateCoordinator
|
coordinator_class: type[DataUpdateCoordinator[Any]] = DataUpdateCoordinator
|
||||||
|
|
||||||
# List of models requiring specific lazy_discover setting
|
|
||||||
LAZY_DISCOVER_FOR_MODEL = {
|
|
||||||
"zhimi.fan.za3": True,
|
|
||||||
"zhimi.fan.za5": True,
|
|
||||||
"zhimi.airpurifier.za1": True,
|
|
||||||
"dmaker.fan.1c": True,
|
|
||||||
}
|
|
||||||
lazy_discover = LAZY_DISCOVER_FOR_MODEL.get(model, False)
|
lazy_discover = LAZY_DISCOVER_FOR_MODEL.get(model, False)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ class YoLinkHomeMessageListener(MessageListener):
|
|||||||
return
|
return
|
||||||
|
|
||||||
device_coordinator.dev_online = True
|
device_coordinator.dev_online = True
|
||||||
if (loraInfo := msg_data.get(ATTR_LORA_INFO)) is not None:
|
if (lora_info := msg_data.get(ATTR_LORA_INFO)) is not None:
|
||||||
device_coordinator.dev_net_type = loraInfo.get("devNetType")
|
device_coordinator.dev_net_type = lora_info.get("devNetType")
|
||||||
device_coordinator.async_set_updated_data(msg_data)
|
device_coordinator.async_set_updated_data(msg_data)
|
||||||
# handling events
|
# handling events
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -710,6 +710,7 @@ select = [
|
|||||||
"LOG", # flake8-logging
|
"LOG", # flake8-logging
|
||||||
"N804", # First argument of a class method should be named cls
|
"N804", # First argument of a class method should be named cls
|
||||||
"N805", # First argument of a method should be named self
|
"N805", # First argument of a method should be named self
|
||||||
|
"N806", # Variable {name} in function should be snake_case
|
||||||
"N815", # Variable {name} in class scope should not be mixedCase
|
"N815", # Variable {name} in class scope should not be mixedCase
|
||||||
"PERF", # Perflint
|
"PERF", # Perflint
|
||||||
"PGH", # pygrep-hooks
|
"PGH", # pygrep-hooks
|
||||||
@@ -928,6 +929,9 @@ split-on-trailing-comma = false
|
|||||||
"homeassistant/scripts/*" = ["T201"]
|
"homeassistant/scripts/*" = ["T201"]
|
||||||
"script/*" = ["T20"]
|
"script/*" = ["T20"]
|
||||||
|
|
||||||
|
# Some utils have constants that benefit from being uppercase
|
||||||
|
"homeassistant/util/*" = ["N806"]
|
||||||
|
|
||||||
# Allow relative imports within auth and within components
|
# Allow relative imports within auth and within components
|
||||||
"homeassistant/auth/*/*" = ["TID252"]
|
"homeassistant/auth/*/*" = ["TID252"]
|
||||||
"homeassistant/components/*/*/*" = ["TID252"]
|
"homeassistant/components/*/*/*" = ["TID252"]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ async def test_setup_and_remove_config_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test setting up and removing a config entry."""
|
"""Test setting up and removing a config entry."""
|
||||||
input_sensor_entity_id = "sensor.input"
|
input_sensor_entity_id = "sensor.input"
|
||||||
NEW_DOMAIN_entity_id = f"{platform}.my_NEW_DOMAIN"
|
new_domain_entity_id = f"{platform}.my_NEW_DOMAIN"
|
||||||
|
|
||||||
# Setup the config entry
|
# Setup the config entry
|
||||||
config_entry = MockConfigEntry(
|
config_entry = MockConfigEntry(
|
||||||
@@ -34,10 +34,10 @@ async def test_setup_and_remove_config_entry(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Check the entity is registered in the entity registry
|
# Check the entity is registered in the entity registry
|
||||||
assert entity_registry.async_get(NEW_DOMAIN_entity_id) is not None
|
assert entity_registry.async_get(new_domain_entity_id) is not None
|
||||||
|
|
||||||
# Check the platform is setup correctly
|
# Check the platform is setup correctly
|
||||||
state = hass.states.get(NEW_DOMAIN_entity_id)
|
state = hass.states.get(new_domain_entity_id)
|
||||||
# TODO Check the state of the entity has changed as expected
|
# TODO Check the state of the entity has changed as expected
|
||||||
assert state.state == "unknown"
|
assert state.state == "unknown"
|
||||||
assert state.attributes == {}
|
assert state.attributes == {}
|
||||||
@@ -47,5 +47,5 @@ async def test_setup_and_remove_config_entry(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Check the state and entity registry entry are removed
|
# Check the state and entity registry entry are removed
|
||||||
assert hass.states.get(NEW_DOMAIN_entity_id) is None
|
assert hass.states.get(new_domain_entity_id) is None
|
||||||
assert entity_registry.async_get(NEW_DOMAIN_entity_id) is None
|
assert entity_registry.async_get(new_domain_entity_id) is None
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ extend = "../pyproject.toml"
|
|||||||
|
|
||||||
extend-ignore = [
|
extend-ignore = [
|
||||||
"B904", # Use raise from to specify exception cause
|
"B904", # Use raise from to specify exception cause
|
||||||
|
"N806", # Variable {name} in function should be snake_case
|
||||||
"N815", # Variable {name} in class scope should not be mixedCase
|
"N815", # Variable {name} in class scope should not be mixedCase
|
||||||
"RUF018", # Avoid assignment expressions in assert statements
|
"RUF018", # Avoid assignment expressions in assert statements
|
||||||
"DTZ011", # date.today() used: tests commonly use naive dates
|
"DTZ011", # date.today() used: tests commonly use naive dates
|
||||||
|
|||||||
Reference in New Issue
Block a user