mirror of https://github.com/home-assistant/core
56 lines
1.8 KiB
Python
56 lines
1.8 KiB
Python
"""ONVIF util."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from zeep.exceptions import Fault
|
|
|
|
|
|
def extract_subcodes_as_strings(subcodes: Any) -> list[str]:
|
|
"""Stringify ONVIF subcodes."""
|
|
if isinstance(subcodes, list):
|
|
return [code.text if hasattr(code, "text") else str(code) for code in subcodes]
|
|
return [str(subcodes)]
|
|
|
|
|
|
def stringify_onvif_error(error: Exception) -> str:
|
|
"""Stringify ONVIF error."""
|
|
if isinstance(error, Fault):
|
|
message = error.message
|
|
if error.detail is not None: # checking true is deprecated
|
|
# Detail may be a bytes object, so we need to convert it to string
|
|
if isinstance(error.detail, bytes):
|
|
detail = error.detail.decode("utf-8", "replace")
|
|
else:
|
|
detail = str(error.detail)
|
|
message += ": " + detail
|
|
if error.code is not None: # checking true is deprecated
|
|
message += f" (code:{error.code})"
|
|
if error.subcodes is not None: # checking true is deprecated
|
|
message += (
|
|
f" (subcodes:{','.join(extract_subcodes_as_strings(error.subcodes))})"
|
|
)
|
|
if error.actor:
|
|
message += f" (actor:{error.actor})"
|
|
else:
|
|
message = str(error)
|
|
return message or f"Device sent empty error with type {type(error)}"
|
|
|
|
|
|
def is_auth_error(error: Exception) -> bool:
|
|
"""Return True if error is an authentication error.
|
|
|
|
Most of the tested cameras do not return a proper error code when
|
|
authentication fails, so we need to check the error message as well.
|
|
"""
|
|
if not isinstance(error, Fault):
|
|
return False
|
|
return (
|
|
any(
|
|
"NotAuthorized" in code
|
|
for code in extract_subcodes_as_strings(error.subcodes)
|
|
)
|
|
or "auth" in stringify_onvif_error(error).lower()
|
|
)
|