From b3b9c52df21a8420cc3e8d18b6bfa8b396e156ad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 25 Sep 2020 22:28:59 -0500 Subject: [PATCH] Add device info to gogogate2 (#40538) --- homeassistant/components/gogogate2/const.py | 1 + homeassistant/components/gogogate2/cover.py | 14 +- tests/components/gogogate2/test_cover.py | 254 +++++++++++--------- 3 files changed, 149 insertions(+), 120 deletions(-) diff --git a/homeassistant/components/gogogate2/const.py b/homeassistant/components/gogogate2/const.py index 5c0ef55ff3f..2f6ac76122f 100644 --- a/homeassistant/components/gogogate2/const.py +++ b/homeassistant/components/gogogate2/const.py @@ -4,3 +4,4 @@ DOMAIN = "gogogate2" DATA_UPDATE_COORDINATOR = "data_update_coordinator" DEVICE_TYPE_GOGOGATE2 = "gogogate2" DEVICE_TYPE_ISMARTGATE = "ismartgate" +MANUFACTURER = "Remsol" diff --git a/homeassistant/components/gogogate2/cover.py b/homeassistant/components/gogogate2/cover.py index 8e753eb6ae5..e748b420edb 100644 --- a/homeassistant/components/gogogate2/cover.py +++ b/homeassistant/components/gogogate2/cover.py @@ -34,7 +34,7 @@ from .common import ( cover_unique_id, get_data_update_coordinator, ) -from .const import DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN +from .const import DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN, MANUFACTURER _LOGGER = logging.getLogger(__name__) @@ -154,3 +154,15 @@ class DeviceCover(CoordinatorEntity, CoverEntity): door = get_door_by_id(self._door.door_id, self.coordinator.data) self._door = door or self._door return self._door + + @property + def device_info(self): + """Device info for the controller.""" + data = self.coordinator.data + return { + "identifiers": {(DOMAIN, self._config_entry.unique_id)}, + "name": self._config_entry.title, + "manufacturer": MANUFACTURER, + "model": data.model, + "sw_version": data.firmwareversion, + } diff --git a/tests/components/gogogate2/test_cover.py b/tests/components/gogogate2/test_cover.py index b1ab2284580..91bffca56ce 100644 --- a/tests/components/gogogate2/test_cover.py +++ b/tests/components/gogogate2/test_cover.py @@ -25,6 +25,7 @@ from homeassistant.components.gogogate2.const import ( DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN, + MANUFACTURER, ) from homeassistant.components.homeassistant import DOMAIN as HA_DOMAIN from homeassistant.config import async_process_ha_core_config @@ -49,54 +50,18 @@ from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow from tests.async_mock import MagicMock, patch -from tests.common import MockConfigEntry, async_fire_time_changed +from tests.common import MockConfigEntry, async_fire_time_changed, mock_device_registry -@patch("homeassistant.components.gogogate2.common.GogoGate2Api") -async def test_import_fail(gogogate2api_mock, hass: HomeAssistant) -> None: - """Test the failure to import.""" - api = MagicMock(spec=GogoGate2Api) - api.info.side_effect = ApiError(22, "Error") - gogogate2api_mock.return_value = api - - hass_config = { - HA_DOMAIN: {CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC}, - COVER_DOMAIN: [ - { - CONF_PLATFORM: "gogogate2", - CONF_NAME: "cover0", - CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, - CONF_IP_ADDRESS: "127.0.1.0", - CONF_USERNAME: "user0", - CONF_PASSWORD: "password0", - } - ], - } - - await async_process_ha_core_config(hass, hass_config[HA_DOMAIN]) - assert await async_setup_component(hass, HA_DOMAIN, {}) - assert await async_setup_component(hass, COVER_DOMAIN, hass_config) - await hass.async_block_till_done() - - entity_ids = hass.states.async_entity_ids(COVER_DOMAIN) - assert not entity_ids - - -@patch("homeassistant.components.gogogate2.common.GogoGate2Api") -@patch("homeassistant.components.gogogate2.common.ISmartGateApi") -async def test_import( - ismartgateapi_mock, gogogate2api_mock, hass: HomeAssistant -) -> None: - """Test importing of file based config.""" - api0 = MagicMock(spec=GogoGate2Api) - api0.info.return_value = GogoGate2InfoResponse( +def _mocked_gogogate_open_door_response(): + return GogoGate2InfoResponse( user="user1", gogogatename="gogogatename0", - model="", + model="gogogate2", apiversion="", remoteaccessenabled=False, remoteaccess="abc123.blah.blah", - firmwareversion="", + firmwareversion="222", apicode="", door1=GogoGate2Door( door_id=1, @@ -144,17 +109,17 @@ async def test_import( network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) - gogogate2api_mock.return_value = api0 - api1 = MagicMock(spec=ISmartGateApi) - api1.info.return_value = ISmartGateInfoResponse( + +def _mocked_ismartgate_closed_door_response(): + return ISmartGateInfoResponse( user="user1", ismartgatename="ismartgatename0", - model="", + model="ismartgatePRO", apiversion="", remoteaccessenabled=False, remoteaccess="abc321.blah.blah", - firmwareversion="", + firmwareversion="555", pin=123, lang="en", newfirmware=False, @@ -176,9 +141,9 @@ async def test_import( voltage=40, ), door2=ISmartGateDoor( - door_id=1, + door_id=2, permission=True, - name=None, + name="Door2", gate=True, mode=DoorMode.GARAGE, status=DoorStatus.CLOSED, @@ -193,16 +158,16 @@ async def test_import( voltage=40, ), door3=ISmartGateDoor( - door_id=1, + door_id=3, permission=True, name=None, gate=False, mode=DoorMode.GARAGE, - status=DoorStatus.CLOSED, + status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, - events=2, + events=0, temperature=None, enabled=True, apicode="apicode0", @@ -212,6 +177,50 @@ async def test_import( network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) + + +@patch("homeassistant.components.gogogate2.common.GogoGate2Api") +async def test_import_fail(gogogate2api_mock, hass: HomeAssistant) -> None: + """Test the failure to import.""" + api = MagicMock(spec=GogoGate2Api) + api.info.side_effect = ApiError(22, "Error") + gogogate2api_mock.return_value = api + + hass_config = { + HA_DOMAIN: {CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC}, + COVER_DOMAIN: [ + { + CONF_PLATFORM: "gogogate2", + CONF_NAME: "cover0", + CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, + CONF_IP_ADDRESS: "127.0.1.0", + CONF_USERNAME: "user0", + CONF_PASSWORD: "password0", + } + ], + } + + await async_process_ha_core_config(hass, hass_config[HA_DOMAIN]) + assert await async_setup_component(hass, HA_DOMAIN, {}) + assert await async_setup_component(hass, COVER_DOMAIN, hass_config) + await hass.async_block_till_done() + + entity_ids = hass.states.async_entity_ids(COVER_DOMAIN) + assert not entity_ids + + +@patch("homeassistant.components.gogogate2.common.GogoGate2Api") +@patch("homeassistant.components.gogogate2.common.ISmartGateApi") +async def test_import( + ismartgateapi_mock, gogogate2api_mock, hass: HomeAssistant +) -> None: + """Test importing of file based config.""" + api0 = MagicMock(spec=GogoGate2Api) + api0.info.return_value = _mocked_gogogate_open_door_response() + gogogate2api_mock.return_value = api0 + + api1 = MagicMock(spec=ISmartGateApi) + api1.info.return_value = _mocked_ismartgate_closed_door_response() ismartgateapi_mock.return_value = api1 hass_config = { @@ -243,13 +252,14 @@ async def test_import( entity_ids = hass.states.async_entity_ids(COVER_DOMAIN) assert entity_ids is not None - assert len(entity_ids) == 2 + assert len(entity_ids) == 3 assert "cover.door1" in entity_ids assert "cover.door1_2" in entity_ids + assert "cover.door2" in entity_ids @patch("homeassistant.components.gogogate2.common.GogoGate2Api") -async def test_open_close_update(gogogat2api_mock, hass: HomeAssistant) -> None: +async def test_open_close_update(gogogate2api_mock, hass: HomeAssistant) -> None: """Test open and close and data update.""" def info_response(door_status: DoorStatus) -> GogoGate2InfoResponse: @@ -312,7 +322,7 @@ async def test_open_close_update(gogogat2api_mock, hass: HomeAssistant) -> None: api = MagicMock(GogoGate2Api) api.activate.return_value = GogoGate2ActivateResponse(result=True) api.info.return_value = info_response(DoorStatus.OPENED) - gogogat2api_mock.return_value = api + gogogate2api_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, @@ -364,71 +374,7 @@ async def test_open_close_update(gogogat2api_mock, hass: HomeAssistant) -> None: @patch("homeassistant.components.gogogate2.common.ISmartGateApi") async def test_availability(ismartgateapi_mock, hass: HomeAssistant) -> None: """Test availability.""" - closed_door_response = ISmartGateInfoResponse( - user="user1", - ismartgatename="ismartgatename0", - model="", - apiversion="", - remoteaccessenabled=False, - remoteaccess="abc123.blah.blah", - firmwareversion="", - pin=123, - lang="en", - newfirmware=False, - door1=ISmartGateDoor( - door_id=1, - permission=True, - name="Door1", - gate=False, - mode=DoorMode.GARAGE, - status=DoorStatus.CLOSED, - sensor=True, - sensorid=None, - camera=False, - events=2, - temperature=None, - enabled=True, - apicode="apicode0", - customimage=False, - voltage=40, - ), - door2=ISmartGateDoor( - door_id=2, - permission=True, - name="Door2", - gate=True, - mode=DoorMode.GARAGE, - status=DoorStatus.CLOSED, - sensor=True, - sensorid=None, - camera=False, - events=2, - temperature=None, - enabled=True, - apicode="apicode0", - customimage=False, - voltage=40, - ), - door3=ISmartGateDoor( - door_id=3, - permission=True, - name=None, - gate=False, - mode=DoorMode.GARAGE, - status=DoorStatus.UNDEFINED, - sensor=True, - sensorid=None, - camera=False, - events=0, - temperature=None, - enabled=True, - apicode="apicode0", - customimage=False, - voltage=40, - ), - network=Network(ip=""), - wifi=Wifi(SSID="", linkquality="", signal=""), - ) + closed_door_response = _mocked_ismartgate_closed_door_response() api = MagicMock(ISmartGateApi) api.info.return_value = closed_door_response @@ -470,3 +416,73 @@ async def test_availability(ismartgateapi_mock, hass: HomeAssistant) -> None: async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_CLOSED + + +@patch("homeassistant.components.gogogate2.common.ISmartGateApi") +async def test_device_info_ismartgate(ismartgateapi_mock, hass: HomeAssistant) -> None: + """Test device info.""" + device_registry = mock_device_registry(hass) + + closed_door_response = _mocked_ismartgate_closed_door_response() + + api = MagicMock(ISmartGateApi) + api.info.return_value = closed_door_response + ismartgateapi_mock.return_value = api + + config_entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + title="mycontroller", + unique_id="xyz", + data={ + CONF_DEVICE: DEVICE_TYPE_ISMARTGATE, + CONF_IP_ADDRESS: "127.0.0.1", + CONF_USERNAME: "admin", + CONF_PASSWORD: "password", + }, + ) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + device = device_registry.async_get_device({(DOMAIN, "xyz")}, set()) + assert device + assert device.manufacturer == MANUFACTURER + assert device.name == "mycontroller" + assert device.model == "ismartgatePRO" + assert device.sw_version == "555" + + +@patch("homeassistant.components.gogogate2.common.GogoGate2Api") +async def test_device_info_gogogate2(gogogate2api_mock, hass: HomeAssistant) -> None: + """Test device info.""" + device_registry = mock_device_registry(hass) + + closed_door_response = _mocked_gogogate_open_door_response() + + api = MagicMock(GogoGate2Api) + api.info.return_value = closed_door_response + gogogate2api_mock.return_value = api + + config_entry = MockConfigEntry( + domain=DOMAIN, + source=SOURCE_USER, + title="mycontroller", + unique_id="xyz", + data={ + CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, + CONF_IP_ADDRESS: "127.0.0.1", + CONF_USERNAME: "admin", + CONF_PASSWORD: "password", + }, + ) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + device = device_registry.async_get_device({(DOMAIN, "xyz")}, set()) + assert device + assert device.manufacturer == MANUFACTURER + assert device.name == "mycontroller" + assert device.model == "gogogate2" + assert device.sw_version == "222"