Remove iAlarm XR integration (#73083)

* fixing after MartinHjelmare review

* fixing after MartinHjelmare review conversion alarm state to hass state

* fixing after MartinHjelmare review conversion alarm state to hass state

* manage the status in the alarm control

* simplyfing return function

* Removing iAlarm XR integration because of Antifurto365 explicit request to remove after some issues in their cloud service
This commit is contained in:
BigMoby 2022-06-07 07:23:10 +02:00 committed by GitHub
parent 16bf6903bd
commit 0c21bf7c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 0 additions and 1042 deletions

View File

@ -518,7 +518,6 @@ omit =
homeassistant/components/hvv_departures/__init__.py
homeassistant/components/hydrawise/*
homeassistant/components/ialarm/alarm_control_panel.py
homeassistant/components/ialarm_xr/alarm_control_panel.py
homeassistant/components/iammeter/sensor.py
homeassistant/components/iaqualink/binary_sensor.py
homeassistant/components/iaqualink/climate.py

View File

@ -128,7 +128,6 @@ homeassistant.components.homewizard.*
homeassistant.components.http.*
homeassistant.components.huawei_lte.*
homeassistant.components.hyperion.*
homeassistant.components.ialarm_xr.*
homeassistant.components.image_processing.*
homeassistant.components.input_button.*
homeassistant.components.input_select.*

View File

@ -475,8 +475,6 @@ build.json @home-assistant/supervisor
/tests/components/hyperion/ @dermotduffy
/homeassistant/components/ialarm/ @RyuzakiKK
/tests/components/ialarm/ @RyuzakiKK
/homeassistant/components/ialarm_xr/ @bigmoby
/tests/components/ialarm_xr/ @bigmoby
/homeassistant/components/iammeter/ @lewei50
/homeassistant/components/iaqualink/ @flz
/tests/components/iaqualink/ @flz

View File

@ -1,101 +0,0 @@
"""iAlarmXR integration."""
from __future__ import annotations
import asyncio
import logging
from async_timeout import timeout
from pyialarmxr import (
IAlarmXR,
IAlarmXRGenericException,
IAlarmXRSocketTimeoutException,
)
from homeassistant.components.alarm_control_panel import SCAN_INTERVAL
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN
from .utils import async_get_ialarmxr_mac
PLATFORMS = [Platform.ALARM_CONTROL_PANEL]
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up iAlarmXR config."""
host = entry.data[CONF_HOST]
port = entry.data[CONF_PORT]
username = entry.data[CONF_USERNAME]
password = entry.data[CONF_PASSWORD]
ialarmxr = IAlarmXR(username, password, host, port)
try:
async with timeout(10):
ialarmxr_mac = await async_get_ialarmxr_mac(hass, ialarmxr)
except (
asyncio.TimeoutError,
ConnectionError,
IAlarmXRGenericException,
IAlarmXRSocketTimeoutException,
) as ex:
raise ConfigEntryNotReady from ex
coordinator = IAlarmXRDataUpdateCoordinator(hass, ialarmxr, ialarmxr_mac)
await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload iAlarmXR config."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)
return unload_ok
class IAlarmXRDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching iAlarmXR data."""
def __init__(self, hass: HomeAssistant, ialarmxr: IAlarmXR, mac: str) -> None:
"""Initialize global iAlarm data updater."""
self.ialarmxr: IAlarmXR = ialarmxr
self.state: int | None = None
self.host: str = ialarmxr.host
self.mac: str = mac
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
update_interval=SCAN_INTERVAL,
)
def _update_data(self) -> None:
"""Fetch data from iAlarmXR via sync functions."""
status: int = self.ialarmxr.get_status()
_LOGGER.debug("iAlarmXR status: %s", status)
self.state = status
async def _async_update_data(self) -> None:
"""Fetch data from iAlarmXR."""
try:
async with timeout(10):
await self.hass.async_add_executor_job(self._update_data)
except ConnectionError as error:
raise UpdateFailed(error) from error

View File

@ -1,79 +0,0 @@
"""Interfaces with iAlarmXR control panels."""
from __future__ import annotations
from pyialarmxr import IAlarmXR
from homeassistant.components.alarm_control_panel import (
AlarmControlPanelEntity,
AlarmControlPanelEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import IAlarmXRDataUpdateCoordinator
from .const import DOMAIN
IALARMXR_TO_HASS = {
IAlarmXR.ARMED_AWAY: STATE_ALARM_ARMED_AWAY,
IAlarmXR.ARMED_STAY: STATE_ALARM_ARMED_HOME,
IAlarmXR.DISARMED: STATE_ALARM_DISARMED,
IAlarmXR.TRIGGERED: STATE_ALARM_TRIGGERED,
}
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up a iAlarmXR alarm control panel based on a config entry."""
coordinator = hass.data[DOMAIN][entry.entry_id]
async_add_entities([IAlarmXRPanel(coordinator)])
class IAlarmXRPanel(
CoordinatorEntity[IAlarmXRDataUpdateCoordinator], AlarmControlPanelEntity
):
"""Representation of an iAlarmXR device."""
_attr_supported_features = (
AlarmControlPanelEntityFeature.ARM_HOME
| AlarmControlPanelEntityFeature.ARM_AWAY
)
_attr_name = "iAlarm_XR"
_attr_icon = "mdi:security"
def __init__(self, coordinator: IAlarmXRDataUpdateCoordinator) -> None:
"""Initialize the alarm panel."""
super().__init__(coordinator)
self._attr_unique_id = coordinator.mac
self._attr_device_info = DeviceInfo(
manufacturer="Antifurto365 - Meian",
name=self.name,
connections={(device_registry.CONNECTION_NETWORK_MAC, coordinator.mac)},
)
@property
def state(self) -> str | None:
"""Return the state of the device."""
return IALARMXR_TO_HASS.get(self.coordinator.state)
def alarm_disarm(self, code: str | None = None) -> None:
"""Send disarm command."""
self.coordinator.ialarmxr.disarm()
def alarm_arm_home(self, code: str | None = None) -> None:
"""Send arm home command."""
self.coordinator.ialarmxr.arm_stay()
def alarm_arm_away(self, code: str | None = None) -> None:
"""Send arm away command."""
self.coordinator.ialarmxr.arm_away()

View File

@ -1,94 +0,0 @@
"""Config flow for Antifurto365 iAlarmXR integration."""
from __future__ import annotations
import logging
from logging import Logger
from typing import Any
from pyialarmxr import (
IAlarmXR,
IAlarmXRGenericException,
IAlarmXRSocketTimeoutException,
)
import voluptuous as vol
from homeassistant import config_entries, core
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
from homeassistant.data_entry_flow import FlowResult
from .const import DOMAIN
from .utils import async_get_ialarmxr_mac
_LOGGER: Logger = logging.getLogger(__name__)
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST, default=IAlarmXR.IALARM_P2P_DEFAULT_HOST): str,
vol.Required(CONF_PORT, default=IAlarmXR.IALARM_P2P_DEFAULT_PORT): int,
vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
}
)
async def _async_get_device_formatted_mac(
hass: core.HomeAssistant, username: str, password: str, host: str, port: int
) -> str:
"""Return iAlarmXR mac address."""
ialarmxr = IAlarmXR(username, password, host, port)
return await async_get_ialarmxr_mac(hass, ialarmxr)
class IAlarmConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Antifurto365 iAlarmXR."""
VERSION = 1
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""
errors = {}
if user_input is not None:
mac = None
host = user_input[CONF_HOST]
port = user_input[CONF_PORT]
username = user_input[CONF_USERNAME]
password = user_input[CONF_PASSWORD]
try:
# If we are able to get the MAC address, we are able to establish
# a connection to the device.
mac = await _async_get_device_formatted_mac(
self.hass, username, password, host, port
)
except ConnectionError:
errors["base"] = "cannot_connect"
except IAlarmXRGenericException as ialarmxr_exception:
_LOGGER.debug(
"IAlarmXRGenericException with message: [ %s ]",
ialarmxr_exception.message,
)
errors["base"] = "cannot_connect"
except IAlarmXRSocketTimeoutException as ialarmxr_socket_timeout_exception:
_LOGGER.debug(
"IAlarmXRSocketTimeoutException with message: [ %s ]",
ialarmxr_socket_timeout_exception.message,
)
errors["base"] = "timeout"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
if not errors:
await self.async_set_unique_id(mac)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=user_input[CONF_HOST], data=user_input
)
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors
)

View File

@ -1,3 +0,0 @@
"""Constants for the iAlarmXR integration."""
DOMAIN = "ialarm_xr"

View File

@ -1,10 +0,0 @@
{
"domain": "ialarm_xr",
"name": "Antifurto365 iAlarmXR",
"documentation": "https://www.home-assistant.io/integrations/ialarm_xr",
"requirements": ["pyialarmxr-homeassistant==1.0.18"],
"codeowners": ["@bigmoby"],
"config_flow": true,
"iot_class": "cloud_polling",
"loggers": ["pyialarmxr"]
}

View File

@ -1,22 +0,0 @@
{
"config": {
"step": {
"user": {
"data": {
"host": "[%key:common::config_flow::data::host%]",
"port": "[%key:common::config_flow::data::port%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]"
}
}
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"timeout": "[%key:common::config_flow::error::timeout_connect%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
}
}

View File

@ -1,21 +0,0 @@
{
"config": {
"abort": {
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e"
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"unknown": "\u041d\u0435\u043e\u0447\u0430\u043a\u0432\u0430\u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0430"
},
"step": {
"user": {
"data": {
"host": "\u0425\u043e\u0441\u0442",
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
"port": "\u041f\u043e\u0440\u0442",
"username": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "El dispositiu ja est\u00e0 configurat"
},
"error": {
"cannot_connect": "Ha fallat la connexi\u00f3",
"timeout": "Temps m\u00e0xim d'espera per establir la connexi\u00f3 esgotat",
"unknown": "Error inesperat"
},
"step": {
"user": {
"data": {
"host": "Amfitri\u00f3",
"password": "Contrasenya",
"port": "Port",
"username": "Nom d'usuari"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Ger\u00e4t ist bereits konfiguriert"
},
"error": {
"cannot_connect": "Verbindung fehlgeschlagen",
"timeout": "Zeit\u00fcberschreitung beim Verbindungsaufbau",
"unknown": "Unerwarteter Fehler"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Passwort",
"port": "Port",
"username": "Benutzername"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "\u0397 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af"
},
"error": {
"cannot_connect": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2",
"timeout": "\u03a7\u03c1\u03bf\u03bd\u03b9\u03ba\u03cc \u03cc\u03c1\u03b9\u03bf \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1\u03c2 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2",
"unknown": "\u0391\u03c0\u03c1\u03cc\u03c3\u03bc\u03b5\u03bd\u03bf \u03c3\u03c6\u03ac\u03bb\u03bc\u03b1"
},
"step": {
"user": {
"data": {
"host": "\u039a\u03b5\u03bd\u03c4\u03c1\u03b9\u03ba\u03cc\u03c2 \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03ae\u03c2",
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"port": "\u0398\u03cd\u03c1\u03b1",
"username": "\u038c\u03bd\u03bf\u03bc\u03b1 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Device is already configured"
},
"error": {
"cannot_connect": "Failed to connect",
"timeout": "Timeout establishing connection",
"unknown": "Unexpected error"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Password",
"port": "Port",
"username": "Username"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "El dispositivo ya est\u00e1 configurado"
},
"error": {
"cannot_connect": "Fallo en la conexi\u00f3n",
"timeout": "Tiempo de espera para establecer la conexi\u00f3n",
"unknown": "Error inesperado"
},
"step": {
"user": {
"data": {
"host": "Anfitri\u00f3n",
"password": "Contrase\u00f1a",
"port": "Puerto",
"username": "Nombre de usuario"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Seade on juba h\u00e4\u00e4lestatud"
},
"error": {
"cannot_connect": "\u00dchendamine nurjus",
"timeout": "\u00dchenduse ajal\u00f5pp",
"unknown": "Ootamatu t\u00f5rge"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Salas\u00f5na",
"port": "Port",
"username": "Kasutajanimi"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "L'appareil est d\u00e9j\u00e0 configur\u00e9"
},
"error": {
"cannot_connect": "\u00c9chec de connexion",
"timeout": "D\u00e9lai d'attente pour \u00e9tablir la connexion expir\u00e9",
"unknown": "Erreur inattendue"
},
"step": {
"user": {
"data": {
"host": "H\u00f4te",
"password": "Mot de passe",
"port": "Port",
"username": "Nom d'utilisateur"
}
}
}
}
}

View File

@ -1,21 +0,0 @@
{
"config": {
"abort": {
"already_configured": "\u05ea\u05e6\u05d5\u05e8\u05ea \u05d4\u05d4\u05ea\u05e7\u05df \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4"
},
"error": {
"cannot_connect": "\u05d4\u05d4\u05ea\u05d7\u05d1\u05e8\u05d5\u05ea \u05e0\u05db\u05e9\u05dc\u05d4",
"unknown": "\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05e6\u05e4\u05d5\u05d9\u05d4"
},
"step": {
"user": {
"data": {
"host": "\u05de\u05d0\u05e8\u05d7",
"password": "\u05e1\u05d9\u05e1\u05de\u05d4",
"port": "\u05e4\u05ea\u05d7\u05d4",
"username": "\u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Az eszk\u00f6z m\u00e1r konfigur\u00e1lva van"
},
"error": {
"cannot_connect": "Sikertelen csatlakoz\u00e1s",
"timeout": "Id\u0151t\u00fall\u00e9p\u00e9s a kapcsolat l\u00e9trehoz\u00e1sa sor\u00e1n",
"unknown": "V\u00e1ratlan hiba t\u00f6rt\u00e9nt"
},
"step": {
"user": {
"data": {
"host": "C\u00edm",
"password": "Jelsz\u00f3",
"port": "Port",
"username": "Felhaszn\u00e1l\u00f3n\u00e9v"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Perangkat sudah dikonfigurasi"
},
"error": {
"cannot_connect": "Gagal terhubung",
"timeout": "Tenggang waktu membuat koneksi habis",
"unknown": "Kesalahan yang tidak diharapkan"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Kata Sandi",
"port": "Port",
"username": "Nama Pengguna"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Il dispositivo \u00e8 gi\u00e0 configurato"
},
"error": {
"cannot_connect": "Impossibile connettersi",
"timeout": "Tempo scaduto per stabile la connessione.",
"unknown": "Errore imprevisto"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Password",
"port": "Porta",
"username": "Nome utente"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
},
"error": {
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
"timeout": "\u63a5\u7d9a\u78ba\u7acb\u6642\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8",
"unknown": "\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc"
},
"step": {
"user": {
"data": {
"host": "\u30db\u30b9\u30c8",
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
"port": "\u30dd\u30fc\u30c8",
"username": "\u30e6\u30fc\u30b6\u30fc\u540d"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Apparaat is al geconfigureerd"
},
"error": {
"cannot_connect": "Kan geen verbinding maken",
"timeout": "Time-out bij het maken van verbinding",
"unknown": "Onverwachte fout"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Wachtwoord",
"port": "Poort",
"username": "Gebruikersnaam"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Enheten er allerede konfigurert"
},
"error": {
"cannot_connect": "Tilkobling mislyktes",
"timeout": "Tidsavbrudd oppretter forbindelse",
"unknown": "Uventet feil"
},
"step": {
"user": {
"data": {
"host": "Vert",
"password": "Passord",
"port": "Port",
"username": "Brukernavn"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane"
},
"error": {
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia",
"timeout": "Limit czasu na nawi\u0105zanie po\u0142\u0105czenia",
"unknown": "Nieoczekiwany b\u0142\u0105d"
},
"step": {
"user": {
"data": {
"host": "Nazwa hosta lub adres IP",
"password": "Has\u0142o",
"port": "Port",
"username": "Nazwa u\u017cytkownika"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "O dispositivo j\u00e1 est\u00e1 configurado"
},
"error": {
"cannot_connect": "Falhou ao se conectar",
"timeout": "Tempo limite estabelecendo conex\u00e3o",
"unknown": "Erro inesperado"
},
"step": {
"user": {
"data": {
"host": "Host",
"password": "Senha",
"port": "Porta",
"username": "Nome de usu\u00e1rio"
}
}
}
}
}

View File

@ -1,21 +0,0 @@
{
"config": {
"abort": {
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
},
"error": {
"cannot_connect": "Ba\u011flanma hatas\u0131",
"unknown": "Beklenmeyen hata"
},
"step": {
"user": {
"data": {
"host": "Sunucu",
"password": "Parola",
"port": "Port",
"username": "Kullan\u0131c\u0131 Ad\u0131"
}
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"config": {
"abort": {
"already_configured": "\u88dd\u7f6e\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210"
},
"error": {
"cannot_connect": "\u9023\u7dda\u5931\u6557",
"timeout": "\u5efa\u7acb\u9023\u7dda\u903e\u6642",
"unknown": "\u672a\u9810\u671f\u932f\u8aa4"
},
"step": {
"user": {
"data": {
"host": "\u4e3b\u6a5f\u7aef",
"password": "\u5bc6\u78bc",
"port": "\u901a\u8a0a\u57e0",
"username": "\u4f7f\u7528\u8005\u540d\u7a31"
}
}
}
}
}

View File

@ -1,18 +0,0 @@
"""iAlarmXR utils."""
import logging
from pyialarmxr import IAlarmXR
from homeassistant import core
from homeassistant.helpers.device_registry import format_mac
_LOGGER = logging.getLogger(__name__)
async def async_get_ialarmxr_mac(hass: core.HomeAssistant, ialarmxr: IAlarmXR) -> str:
"""Retrieve iAlarmXR MAC address."""
_LOGGER.debug("Retrieving ialarmxr mac address")
mac = await hass.async_add_executor_job(ialarmxr.get_mac)
return format_mac(mac)

View File

@ -161,7 +161,6 @@ FLOWS = {
"hvv_departures",
"hyperion",
"ialarm",
"ialarm_xr",
"iaqualink",
"icloud",
"ifttt",

View File

@ -1171,17 +1171,6 @@ no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.ialarm_xr.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.image_processing.*]
check_untyped_defs = true
disallow_incomplete_defs = true

View File

@ -1552,9 +1552,6 @@ pyhomeworks==0.0.6
# homeassistant.components.ialarm
pyialarm==1.9.0
# homeassistant.components.ialarm_xr
pyialarmxr-homeassistant==1.0.18
# homeassistant.components.icloud
pyicloud==1.0.0

View File

@ -1040,9 +1040,6 @@ pyhomematic==0.1.77
# homeassistant.components.ialarm
pyialarm==1.9.0
# homeassistant.components.ialarm_xr
pyialarmxr-homeassistant==1.0.18
# homeassistant.components.icloud
pyicloud==1.0.0

View File

@ -1 +0,0 @@
"""Tests for the Antifurto365 iAlarmXR integration."""

View File

@ -1,167 +0,0 @@
"""Test the Antifurto365 iAlarmXR config flow."""
from unittest.mock import patch
from pyialarmxr import IAlarmXRGenericException, IAlarmXRSocketTimeoutException
from homeassistant import config_entries, data_entry_flow
from homeassistant.components.ialarm_xr.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
from tests.common import MockConfigEntry
TEST_DATA = {
CONF_HOST: "1.1.1.1",
CONF_PORT: 18034,
CONF_USERNAME: "000ZZZ0Z00",
CONF_PASSWORD: "00000000",
}
TEST_MAC = "00:00:54:12:34:56"
async def test_form(hass):
"""Test we get the form."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["handler"] == "ialarm_xr"
assert result["data_schema"].schema.get("host") == str
assert result["data_schema"].schema.get("port") == int
assert result["data_schema"].schema.get("password") == str
assert result["data_schema"].schema.get("username") == str
assert result["errors"] == {}
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_status",
return_value=1,
), patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
return_value=TEST_MAC,
), patch(
"homeassistant.components.ialarm_xr.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
await hass.async_block_till_done()
assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == TEST_DATA["host"]
assert result2["data"] == TEST_DATA
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_exception(hass):
"""Test we handle unknown exception."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
side_effect=Exception,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result2["errors"] == {"base": "unknown"}
async def test_form_cannot_connect_throwing_connection_error(hass):
"""Test we handle cannot connect error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
side_effect=ConnectionError,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result2["errors"] == {"base": "cannot_connect"}
async def test_form_cannot_connect_throwing_socket_timeout_exception(hass):
"""Test we handle cannot connect error because of socket timeout."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
side_effect=IAlarmXRSocketTimeoutException,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result2["errors"] == {"base": "timeout"}
async def test_form_cannot_connect_throwing_generic_exception(hass):
"""Test we handle cannot connect error."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
side_effect=IAlarmXRGenericException,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result2["errors"] == {"base": "cannot_connect"}
async def test_form_already_exists(hass):
"""Test that a flow with an existing host aborts."""
entry = MockConfigEntry(
domain=DOMAIN,
unique_id=TEST_MAC,
data=TEST_DATA,
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.ialarm_xr.config_flow.IAlarmXR.get_mac",
return_value=TEST_MAC,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], TEST_DATA
)
assert result2["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result2["reason"] == "already_configured"
async def test_flow_user_step_no_input(hass):
"""Test appropriate error when no input is provided."""
_result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result = await hass.config_entries.flow.async_configure(
_result["flow_id"], user_input=None
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["step_id"] == config_entries.SOURCE_USER
assert result["errors"] == {}

View File

@ -1,110 +0,0 @@
"""Test the Antifurto365 iAlarmXR init."""
import asyncio
from datetime import timedelta
from unittest.mock import Mock, patch
from uuid import uuid4
import pytest
from homeassistant.components.ialarm_xr.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
from homeassistant.util.dt import utcnow
from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture(name="ialarmxr_api")
def ialarmxr_api_fixture():
"""Set up IAlarmXR API fixture."""
with patch("homeassistant.components.ialarm_xr.IAlarmXR") as mock_ialarm_api:
yield mock_ialarm_api
@pytest.fixture(name="mock_config_entry")
def mock_config_fixture():
"""Return a fake config entry."""
return MockConfigEntry(
domain=DOMAIN,
data={
CONF_HOST: "192.168.10.20",
CONF_PORT: 18034,
CONF_USERNAME: "000ZZZ0Z00",
CONF_PASSWORD: "00000000",
},
entry_id=str(uuid4()),
)
async def test_setup_entry(hass, ialarmxr_api, mock_config_entry):
"""Test setup entry."""
ialarmxr_api.return_value.get_mac = Mock(return_value="00:00:54:12:34:56")
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
ialarmxr_api.return_value.get_mac.assert_called_once()
assert mock_config_entry.state is ConfigEntryState.LOADED
async def test_unload_entry(hass, ialarmxr_api, mock_config_entry):
"""Test being able to unload an entry."""
ialarmxr_api.return_value.get_mac = Mock(return_value="00:00:54:12:34:56")
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
async def test_setup_not_ready_connection_error(hass, ialarmxr_api, mock_config_entry):
"""Test setup failed because we can't connect to the alarm system."""
ialarmxr_api.return_value.get_status = Mock(side_effect=ConnectionError)
mock_config_entry.add_to_hass(hass)
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
future = utcnow() + timedelta(seconds=30)
async_fire_time_changed(hass, future)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setup_not_ready_timeout(hass, ialarmxr_api, mock_config_entry):
"""Test setup failed because we can't connect to the alarm system."""
ialarmxr_api.return_value.get_status = Mock(side_effect=asyncio.TimeoutError)
mock_config_entry.add_to_hass(hass)
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
future = utcnow() + timedelta(seconds=30)
async_fire_time_changed(hass, future)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setup_entry_and_then_fail_on_update(
hass, ialarmxr_api, mock_config_entry
):
"""Test setup entry."""
ialarmxr_api.return_value.get_mac = Mock(return_value="00:00:54:12:34:56")
ialarmxr_api.return_value.get_status = Mock(value=ialarmxr_api.DISARMED)
mock_config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
ialarmxr_api.return_value.get_mac.assert_called_once()
ialarmxr_api.return_value.get_status.assert_called_once()
assert mock_config_entry.state is ConfigEntryState.LOADED
ialarmxr_api.return_value.get_status = Mock(side_effect=asyncio.TimeoutError)
future = utcnow() + timedelta(seconds=60)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
ialarmxr_api.return_value.get_status.assert_called_once()
assert hass.states.get("alarm_control_panel.ialarm_xr").state == "unavailable"