async def test_option_flow_existing(hass, mock_panel): """Test config flow options with existing already in place.""" device_options = config_flow.OPTIONS_SCHEMA( { "io": { "1": "Binary Sensor", "2": "Digital Sensor", "3": "Switchable Output", }, "binary_sensors": [ {"zone": "1", "type": "window", "name": "winder", "inverse": True}, ], "sensors": [{"zone": "2", "type": "ds18b20", "name": "temper"}], "switches": [ { "zone": "3", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, ], } ) device_config = config_flow.CONFIG_ENTRY_SCHEMA( { "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({"io": {}}), } ) entry = MockConfigEntry( domain="konnected", data=device_config, options=device_options, unique_id="112233445566", ) entry.add_to_hass(hass) result = await hass.config_entries.options.async_init( entry.entry_id, context={"source": "test"} ) assert result["type"] == "form" assert result["step_id"] == "options_io" # confirm the defaults are pulled in from the existing options schema = result["data_schema"]({}) assert schema["1"] == "Binary Sensor" assert schema["2"] == "Digital Sensor" assert schema["3"] == "Switchable Output"
async def test_flow_works(hass, mock_panel): """Test config flow .""" result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, context={"source": config_entries.SOURCE_USER} ) assert result["type"] == "form" assert result["step_id"] == "user" mock_panel.get_status.return_value = { "mac": "11:22:33:44:55:66", "model": "Konnected", } result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={"port": 1234, "host": "1.2.3.4"} ) assert result["type"] == "form" assert result["step_id"] == "confirm" assert result["description_placeholders"] == { "model": "Konnected Alarm Panel", "id": "112233445566", "host": "1.2.3.4", "port": 1234, } result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input={} ) assert result["type"] == "create_entry" assert result["data"]["host"] == "1.2.3.4" assert result["data"]["port"] == 1234 assert result["data"]["model"] == "Konnected" assert len(result["data"]["access_token"]) == 20 # confirm generated token size assert result["data"]["default_options"] == config_flow.OPTIONS_SCHEMA( {config_flow.CONF_IO: {}} )
async def test_state_updates(hass, aiohttp_client, mock_panel): """Test callback view.""" await async_setup_component(hass, "http", {"http": {}}) device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "abcdefgh", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({ "io": { "1": "Binary Sensor", "2": "Binary Sensor", "3": "Binary Sensor", "4": "Digital Sensor", "5": "Digital Sensor", "6": "Switchable Output", "out": "Switchable Output", }, "binary_sensors": [ { "zone": "1", "type": "door" }, { "zone": "2", "type": "window", "name": "winder", "inverse": True }, { "zone": "3", "type": "door" }, ], "sensors": [ { "zone": "4", "type": "dht" }, { "zone": "5", "type": "ds18b20", "name": "temper" }, ], "switches": [ { "zone": "out", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "zone": "6" }, ], }) entry = MockConfigEntry( domain="konnected", title="Konnected Alarm Panel", data=device_config, options=device_options, ) entry.add_to_hass(hass) # Add empty data field to ensure we process it correctly (possible if entry is ignored) entry = MockConfigEntry(domain="konnected", title="Konnected Alarm Panel", data={}) entry.add_to_hass(hass) assert (await async_setup_component( hass, konnected.DOMAIN, {konnected.DOMAIN: { konnected.CONF_ACCESS_TOKEN: "1122334455" }}, ) is True) client = await aiohttp_client(hass.http.app) # Test updating a binary sensor resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "1", "state": 0 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get( "binary_sensor.konnected_445566_zone_1").state == "off" resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "1", "state": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get( "binary_sensor.konnected_445566_zone_1").state == "on" # Test updating sht sensor resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "4", "temp": 22, "humi": 20 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get( "sensor.konnected_445566_sensor_4_humidity").state == "20" assert (hass.states.get( "sensor.konnected_445566_sensor_4_temperature").state == "22.0") resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "4", "temp": 25, "humi": 23 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get( "sensor.konnected_445566_sensor_4_humidity").state == "23" assert (hass.states.get( "sensor.konnected_445566_sensor_4_temperature").state == "25.0") # Test updating ds sensor resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "5", "temp": 32, "addr": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get("sensor.temper_temperature").state == "32.0" resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "5", "temp": 42, "addr": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await hass.async_block_till_done() assert hass.states.get("sensor.temper_temperature").state == "42.0"
async def test_api(hass, aiohttp_client, mock_panel): """Test callback view.""" await async_setup_component(hass, "http", {"http": {}}) device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "abcdefgh", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({ "io": { "1": "Binary Sensor", "2": "Binary Sensor", "3": "Binary Sensor", "4": "Digital Sensor", "5": "Digital Sensor", "6": "Switchable Output", "out": "Switchable Output", }, "binary_sensors": [ { "zone": "1", "type": "door" }, { "zone": "2", "type": "window", "name": "winder", "inverse": True }, { "zone": "3", "type": "door" }, ], "sensors": [ { "zone": "4", "type": "dht" }, { "zone": "5", "type": "ds18b20", "name": "temper" }, ], "switches": [ { "zone": "out", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "zone": "6" }, ], }) entry = MockConfigEntry( domain="konnected", title="Konnected Alarm Panel", data=device_config, options=device_options, ) entry.add_to_hass(hass) assert (await async_setup_component( hass, konnected.DOMAIN, {konnected.DOMAIN: { konnected.CONF_ACCESS_TOKEN: "globaltoken" }}, ) is True) client = await aiohttp_client(hass.http.app) # Test the get endpoint for switch status polling resp = await client.get("/api/konnected") assert resp.status == HTTP_NOT_FOUND # no device provided resp = await client.get("/api/konnected/223344556677") assert resp.status == HTTP_NOT_FOUND # unknown device provided resp = await client.get("/api/konnected/device/112233445566") assert resp.status == HTTP_NOT_FOUND # no zone provided result = await resp.json() assert result == { "message": "Switch on zone or pin unknown not configured" } resp = await client.get("/api/konnected/device/112233445566?zone=8") assert resp.status == HTTP_NOT_FOUND # invalid zone result = await resp.json() assert result == {"message": "Switch on zone or pin 8 not configured"} resp = await client.get("/api/konnected/device/112233445566?pin=12") assert resp.status == HTTP_NOT_FOUND # invalid pin result = await resp.json() assert result == {"message": "Switch on zone or pin 12 not configured"} resp = await client.get("/api/konnected/device/112233445566?zone=out") assert resp.status == 200 result = await resp.json() assert result == {"state": 1, "zone": "out"} resp = await client.get("/api/konnected/device/112233445566?pin=8") assert resp.status == 200 result = await resp.json() assert result == {"state": 1, "pin": "8"} # Test the post endpoint for sensor updates resp = await client.post("/api/konnected/device", json={ "zone": "1", "state": 1 }) assert resp.status == HTTP_NOT_FOUND resp = await client.post("/api/konnected/device/112233445566", json={ "zone": "1", "state": 1 }) assert resp.status == 401 result = await resp.json() assert result == {"message": "unauthorized"} resp = await client.post( "/api/konnected/device/223344556677", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "1", "state": 1 }, ) assert resp.status == 400 resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "15", "state": 1 }, ) assert resp.status == 400 result = await resp.json() assert result == {"message": "unregistered sensor/actuator"} resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "1", "state": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer globaltoken"}, json={ "zone": "1", "state": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "4", "temp": 22, "humi": 20 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} # Test the put endpoint for sensor updates resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "zone": "1", "state": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"}
async def test_option_flow(hass, mock_panel): """Test config flow options.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({"io": {}}) entry = MockConfigEntry( domain="konnected", data=device_config, options=device_options, unique_id="112233445566", ) entry.add_to_hass(hass) result = await hass.config_entries.options.async_init( entry.entry_id, context={"source": "test"}) assert result["type"] == "form" assert result["step_id"] == "options_io" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "1": "Disabled", "2": "Binary Sensor", "3": "Digital Sensor", "4": "Switchable Output", "5": "Disabled", "6": "Binary Sensor", "out": "Switchable Output", }, ) assert result["type"] == "form" assert result["step_id"] == "options_binary" assert result["description_placeholders"] == { "zone": "Zone 2", } # zone 2 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "door"}) assert result["type"] == "form" assert result["step_id"] == "options_binary" assert result["description_placeholders"] == { "zone": "Zone 6", } # zone 6 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "type": "window", "name": "winder", "inverse": True }, ) assert result["type"] == "form" assert result["step_id"] == "options_digital" assert result["description_placeholders"] == { "zone": "Zone 3", } # zone 3 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "dht"}) assert result["type"] == "form" assert result["step_id"] == "options_switch" assert result["description_placeholders"] == { "zone": "Zone 4", "state": "1", } # zone 4 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_switch" assert result["description_placeholders"] == { "zone": "OUT", "state": "1", } # zone out result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, "more_states": "Yes", }, ) assert result["type"] == "form" assert result["step_id"] == "options_switch" assert result["description_placeholders"] == { "zone": "OUT", "state": "2", } # zone out - state 2 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "name": "alarm", "activation": "low", "momentary": 100, "pause": 100, "repeat": -1, "more_states": "No", }, ) assert result["type"] == "form" assert result["step_id"] == "options_misc" # make sure we enforce url format result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "discovery": False, "blink": True, "override_api_host": True, "api_host": "badhosturl", }, ) assert result["type"] == "form" assert result["step_id"] == "options_misc" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "discovery": False, "blink": True, "override_api_host": True, "api_host": "http://overridehost:1111", }, ) assert result["type"] == "create_entry" assert result["data"] == { "io": { "2": "Binary Sensor", "3": "Digital Sensor", "4": "Switchable Output", "6": "Binary Sensor", "out": "Switchable Output", }, "discovery": False, "blink": True, "api_host": "http://overridehost:1111", "binary_sensors": [ { "zone": "2", "type": "door", "inverse": False }, { "zone": "6", "type": "window", "name": "winder", "inverse": True }, ], "sensors": [{ "zone": "3", "type": "dht", "poll_interval": 3 }], "switches": [ { "activation": "high", "zone": "4" }, { "zone": "out", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "zone": "out", "name": "alarm", "activation": "low", "momentary": 100, "pause": 100, "repeat": -1, }, ], }
async def test_ssdp_host_update(hass, mock_panel): """Test if a discovered panel has already been configured but changed host.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({ "io": { "2": "Binary Sensor", "6": "Binary Sensor", "10": "Binary Sensor", "3": "Digital Sensor", "7": "Digital Sensor", "11": "Binary Sensor", "4": "Switchable Output", "out1": "Switchable Output", "alarm1": "Switchable Output", }, "binary_sensors": [ { "zone": "2", "type": "door" }, { "zone": "6", "type": "window", "name": "winder", "inverse": True }, { "zone": "10", "type": "door" }, { "zone": "11", "type": "window" }, ], "sensors": [ { "zone": "3", "type": "dht" }, { "zone": "7", "type": "ds18b20", "name": "temper" }, ], "switches": [ { "zone": "4" }, { "zone": "8", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "zone": "out1" }, { "zone": "alarm1" }, ], }) MockConfigEntry( domain="konnected", data=device_config, options=device_options, unique_id="112233445566", ).add_to_hass(hass) mock_panel.get_status.return_value = { "mac": "11:22:33:44:55:66", "model": "Konnected Pro", } result = await hass.config_entries.flow.async_init( config_flow.DOMAIN, context={"source": "ssdp"}, data={ "ssdp_location": "http://1.1.1.1:1234/Device.xml", "manufacturer": config_flow.KONN_MANUFACTURER, "modelName": config_flow.KONN_MODEL_PRO, }, ) assert result["type"] == "abort" # confirm the host value was updated, access_token was not entry = hass.config_entries.async_entries(config_flow.DOMAIN)[0] assert entry.data["host"] == "1.1.1.1" assert entry.data["port"] == 1234 assert entry.data["access_token"] == "11223344556677889900"
async def test_option_flow_import(hass, mock_panel): """Test config flow options imported from configuration.yaml.""" device_options = config_flow.OPTIONS_SCHEMA({ "io": { "1": "Binary Sensor", "2": "Digital Sensor", "3": "Switchable Output", }, "binary_sensors": [ { "zone": "1", "type": "window", "name": "winder", "inverse": True }, ], "sensors": [{ "zone": "2", "type": "ds18b20", "name": "temper" }], "switches": [ { "zone": "3", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "zone": "3", "name": "alarm", "activation": "low", "momentary": 100, "pause": 100, "repeat": -1, }, ], }) device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": device_options, }) entry = MockConfigEntry(domain="konnected", data=device_config, unique_id="112233445566") entry.add_to_hass(hass) result = await hass.config_entries.options.async_init( entry.entry_id, context={"source": "test"}) assert result["type"] == "form" assert result["step_id"] == "options_io" # confirm the defaults are set based on current config - we"ll spot check this throughout schema = result["data_schema"]({}) assert schema["1"] == "Binary Sensor" assert schema["2"] == "Digital Sensor" assert schema["3"] == "Switchable Output" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "1": "Binary Sensor", "2": "Digital Sensor", "3": "Switchable Output", }, ) assert result["type"] == "form" assert result["step_id"] == "options_io_ext" schema = result["data_schema"]({}) assert schema["8"] == "Disabled" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={}, ) assert result["type"] == "form" assert result["step_id"] == "options_binary" # zone 1 schema = result["data_schema"]({}) assert schema["type"] == "window" assert schema["name"] == "winder" assert schema["inverse"] is True result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "door"}) assert result["type"] == "form" assert result["step_id"] == "options_digital" # zone 2 schema = result["data_schema"]({}) assert schema["type"] == "ds18b20" assert schema["name"] == "temper" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "dht"}, ) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone 3 schema = result["data_schema"]({}) assert schema["name"] == "switcher" assert schema["activation"] == "low" assert schema["momentary"] == 50 assert schema["pause"] == 100 assert schema["repeat"] == 4 assert schema["more_states"] == "Yes" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "activation": "high", "more_states": "No" }) assert result["type"] == "form" assert result["step_id"] == "options_misc" schema = result["data_schema"]({}) assert schema["blink"] is True assert schema["discovery"] is True result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "discovery": True, "blink": False, "override_api_host": False }, ) # verify the updated fields assert result["type"] == "create_entry" assert result["data"] == { "io": { "1": "Binary Sensor", "2": "Digital Sensor", "3": "Switchable Output" }, "discovery": True, "blink": False, "api_host": "", "binary_sensors": [ { "zone": "1", "type": "door", "inverse": True, "name": "winder" }, ], "sensors": [ { "zone": "2", "type": "dht", "poll_interval": 3, "name": "temper" }, ], "switches": [ { "zone": "3", "name": "switcher", "activation": "high", "momentary": 50, "pause": 100, "repeat": 4, }, ], }
async def test_option_flow_pro(hass, mock_panel): """Test config flow options for pro board.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({"io": {}}) entry = MockConfigEntry( domain="konnected", data=device_config, options=device_options, unique_id="112233445566", ) entry.add_to_hass(hass) result = await hass.config_entries.options.async_init( entry.entry_id, context={"source": "test"}) assert result["type"] == "form" assert result["step_id"] == "options_io" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "1": "Disabled", "2": "Binary Sensor", "3": "Digital Sensor", "4": "Switchable Output", "5": "Disabled", "6": "Binary Sensor", "7": "Digital Sensor", }, ) assert result["type"] == "form" assert result["step_id"] == "options_io_ext" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "8": "Switchable Output", "9": "Disabled", "10": "Binary Sensor", "11": "Binary Sensor", "12": "Disabled", "out1": "Switchable Output", "alarm1": "Switchable Output", "alarm2_out2": "Disabled", }, ) assert result["type"] == "form" assert result["step_id"] == "options_binary" # zone 2 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "door"}) assert result["type"] == "form" assert result["step_id"] == "options_binary" # zone 6 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "type": "window", "name": "winder", "inverse": True }, ) assert result["type"] == "form" assert result["step_id"] == "options_binary" # zone 10 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "door"}) assert result["type"] == "form" assert result["step_id"] == "options_binary" # zone 11 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "window"}) assert result["type"] == "form" assert result["step_id"] == "options_digital" # zone 3 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"type": "dht"}) assert result["type"] == "form" assert result["step_id"] == "options_digital" # zone 7 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "type": "ds18b20", "name": "temper" }) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone 4 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone 8 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, ) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone out1 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone alarm1 result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_misc" result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={ "discovery": False, "blink": True, "override_api_host": False }, ) assert result["type"] == "create_entry" assert result["data"] == { "io": { "10": "Binary Sensor", "11": "Binary Sensor", "2": "Binary Sensor", "3": "Digital Sensor", "4": "Switchable Output", "6": "Binary Sensor", "7": "Digital Sensor", "8": "Switchable Output", "alarm1": "Switchable Output", "out1": "Switchable Output", }, "discovery": False, "blink": True, "api_host": "", "binary_sensors": [ { "zone": "2", "type": "door", "inverse": False }, { "zone": "6", "type": "window", "name": "winder", "inverse": True }, { "zone": "10", "type": "door", "inverse": False }, { "zone": "11", "type": "window", "inverse": False }, ], "sensors": [ { "zone": "3", "type": "dht", "poll_interval": 3 }, { "zone": "7", "type": "ds18b20", "name": "temper", "poll_interval": 3 }, ], "switches": [ { "activation": "high", "zone": "4" }, { "zone": "8", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, { "activation": "high", "zone": "out1" }, { "activation": "high", "zone": "alarm1" }, ], }
async def test_connect_retry(hass, mock_panel): """Test that we create a Konnected Panel and save the data.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA( { "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA( { "io": { "1": "Binary Sensor", "2": "Binary Sensor", "3": "Binary Sensor", "4": "Digital Sensor", "5": "Digital Sensor", "6": "Switchable Output", "out": "Switchable Output", }, "binary_sensors": [ {"zone": "1", "type": "door"}, { "zone": "2", "type": "window", "name": "winder", "inverse": True, }, {"zone": "3", "type": "door"}, ], "sensors": [ {"zone": "4", "type": "dht"}, {"zone": "5", "type": "ds18b20", "name": "temper"}, ], "switches": [ { "zone": "out", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, {"zone": "6"}, ], } ), } ) entry = MockConfigEntry( domain="konnected", title="Konnected Alarm Panel", data=device_config, options={}, ) entry.add_to_hass(hass) # fail first 2 attempts, and succeed the third mock_panel.get_status.side_effect = [ mock_panel.ClientError, mock_panel.ClientError, { "hwVersion": "2.3.0", "swVersion": "2.3.1", "heap": 10000, "uptime": 12222, "ip": "192.168.1.90", "port": 9123, "sensors": [], "actuators": [], "dht_sensors": [], "ds18b20_sensors": [], "mac": "11:22:33:44:55:66", "model": "Konnected Pro", "settings": {}, }, ] # setup the integration and inspect panel behavior assert ( await async_setup_component( hass, panel.DOMAIN, { panel.DOMAIN: { panel.CONF_ACCESS_TOKEN: "arandomstringvalue", panel.CONF_API_HOST: "http://192.168.1.1:8123", } }, ) is True ) # confirm switch is unavailable after initial attempt await hass.async_block_till_done() assert hass.states.get("switch.konnected_445566_actuator_6").state == "unavailable" # confirm switch is unavailable after second attempt async_fire_time_changed(hass, utcnow() + timedelta(seconds=11)) await hass.async_block_till_done() await hass.helpers.entity_component.async_update_entity( "switch.konnected_445566_actuator_6" ) assert hass.states.get("switch.konnected_445566_actuator_6").state == "unavailable" # confirm switch is available after third attempt async_fire_time_changed(hass, utcnow() + timedelta(seconds=21)) await hass.async_block_till_done() await hass.helpers.entity_component.async_update_entity( "switch.konnected_445566_actuator_6" ) assert hass.states.get("switch.konnected_445566_actuator_6").state == "off"
async def test_create_and_setup(hass, mock_panel): """Test that we create a Konnected Panel and save the data.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA( { "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), } ) device_options = config_flow.OPTIONS_SCHEMA( { "io": { "1": "Binary Sensor", "2": "Binary Sensor", "3": "Binary Sensor", "4": "Digital Sensor", "5": "Digital Sensor", "6": "Switchable Output", "out": "Switchable Output", }, "binary_sensors": [ {"zone": "1", "type": "door"}, {"zone": "2", "type": "window", "name": "winder", "inverse": True}, {"zone": "3", "type": "door"}, ], "sensors": [ {"zone": "4", "type": "dht"}, {"zone": "5", "type": "ds18b20", "name": "temper"}, ], "switches": [ { "zone": "out", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, {"zone": "6"}, ], } ) entry = MockConfigEntry( domain="konnected", title="Konnected Alarm Panel", data=device_config, options=device_options, ) entry.add_to_hass(hass) # override get_status to reflect non-pro board mock_panel.get_status.return_value = { "hwVersion": "2.3.0", "swVersion": "2.3.1", "heap": 10000, "uptime": 12222, "ip": "192.168.1.90", "port": 9123, "sensors": [], "actuators": [], "dht_sensors": [], "ds18b20_sensors": [], "mac": "11:22:33:44:55:66", "settings": {}, } # setup the integration and inspect panel behavior assert ( await async_setup_component( hass, panel.DOMAIN, { panel.DOMAIN: { panel.CONF_ACCESS_TOKEN: "arandomstringvalue", panel.CONF_API_HOST: "http://192.168.1.1:8123", } }, ) is True ) # confirm panel instance was created and configured # hass.data is the only mechanism to get a reference to the created panel instance device = hass.data[panel.DOMAIN][panel.CONF_DEVICES]["112233445566"]["panel"] await device.update_switch("1", 0) # confirm the correct api is used # pylint: disable=no-member assert mock_panel.put_device.call_count == 1 assert mock_panel.put_zone.call_count == 0 # confirm the settings are sent to the panel # pylint: disable=no-member assert mock_panel.put_settings.call_args_list[0][1] == { "sensors": [{"pin": "1"}, {"pin": "2"}, {"pin": "5"}], "actuators": [{"trigger": 0, "pin": "8"}, {"trigger": 1, "pin": "9"}], "dht_sensors": [{"poll_interval": 3, "pin": "6"}], "ds18b20_sensors": [{"pin": "7"}], "auth_token": "11223344556677889900", "blink": True, "discovery": True, "endpoint": "http://192.168.1.1:8123/api/konnected", } # confirm the device settings are saved in hass.data assert device.stored_configuration == { "binary_sensors": { "1": { "inverse": False, "name": "Konnected 445566 Zone 1", "state": None, "type": "door", }, "2": {"inverse": True, "name": "winder", "state": None, "type": "window"}, "3": { "inverse": False, "name": "Konnected 445566 Zone 3", "state": None, "type": "door", }, }, "blink": True, "panel": device, "discovery": True, "host": "1.2.3.4", "port": 1234, "sensors": [ { "name": "Konnected 445566 Sensor 4", "poll_interval": 3, "type": "dht", "zone": "4", }, {"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "5"}, ], "switches": [ { "activation": "low", "momentary": 50, "name": "switcher", "pause": 100, "repeat": 4, "state": None, "zone": "out", }, { "activation": "high", "momentary": None, "name": "Konnected 445566 Actuator 6", "pause": None, "repeat": None, "state": None, "zone": "6", }, ], }
async def test_create_and_setup_pro(hass, mock_panel): """Test that we create a Konnected Pro Panel and save the data.""" device_config = config_flow.CONFIG_ENTRY_SCHEMA( { "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "11223344556677889900", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), } ) device_options = config_flow.OPTIONS_SCHEMA( { "io": { "2": "Binary Sensor", "6": "Binary Sensor", "10": "Binary Sensor", "3": "Digital Sensor", "7": "Digital Sensor", "11": "Digital Sensor", "4": "Switchable Output", "8": "Switchable Output", "out1": "Switchable Output", "alarm1": "Switchable Output", }, "binary_sensors": [ {"zone": "2", "type": "door"}, {"zone": "6", "type": "window", "name": "winder", "inverse": True}, {"zone": "10", "type": "door"}, ], "sensors": [ {"zone": "3", "type": "dht"}, {"zone": "7", "type": "ds18b20", "name": "temper"}, {"zone": "11", "type": "dht", "poll_interval": 5}, ], "switches": [ {"zone": "4"}, { "zone": "8", "name": "switcher", "activation": "low", "momentary": 50, "pause": 100, "repeat": 4, }, {"zone": "out1"}, {"zone": "alarm1"}, ], } ) entry = MockConfigEntry( domain="konnected", title="Konnected Pro Alarm Panel", data=device_config, options=device_options, ) entry.add_to_hass(hass) hass.data[panel.DOMAIN] = { panel.CONF_API_HOST: "192.168.1.1", } device = panel.AlarmPanel(hass, entry) await device.async_save_data() await device.async_connect() await device.update_switch("2", 1) # confirm the correct api is used # pylint: disable=no-member assert device.client.put_device.call_count == 0 assert device.client.put_zone.call_count == 1 # confirm the settings are sent to the panel # pylint: disable=no-member assert device.client.put_settings.call_args_list[0][1] == { "sensors": [{"zone": "2"}, {"zone": "6"}, {"zone": "10"}], "actuators": [ {"trigger": 1, "zone": "4"}, {"trigger": 0, "zone": "8"}, {"trigger": 1, "zone": "out1"}, {"trigger": 1, "zone": "alarm1"}, ], "dht_sensors": [ {"poll_interval": 3, "zone": "3"}, {"poll_interval": 5, "zone": "11"}, ], "ds18b20_sensors": [{"zone": "7"}], "auth_token": "11223344556677889900", "blink": True, "discovery": True, "endpoint": "192.168.1.1/api/konnected", } # confirm the device settings are saved in hass.data assert hass.data[panel.DOMAIN][panel.CONF_DEVICES] == { "112233445566": { "binary_sensors": { "10": { "inverse": False, "name": "Konnected 445566 Zone 10", "state": None, "type": "door", }, "2": { "inverse": False, "name": "Konnected 445566 Zone 2", "state": None, "type": "door", }, "6": { "inverse": True, "name": "winder", "state": None, "type": "window", }, }, "blink": True, "panel": device, "discovery": True, "host": "1.2.3.4", "port": 1234, "sensors": [ { "name": "Konnected 445566 Sensor 3", "poll_interval": 3, "type": "dht", "zone": "3", }, {"name": "temper", "poll_interval": 3, "type": "ds18b20", "zone": "7"}, { "name": "Konnected 445566 Sensor 11", "poll_interval": 5, "type": "dht", "zone": "11", }, ], "switches": [ { "activation": "high", "momentary": None, "name": "Konnected 445566 Actuator 4", "pause": None, "repeat": None, "state": None, "zone": "4", }, { "activation": "low", "momentary": 50, "name": "switcher", "pause": 100, "repeat": 4, "state": None, "zone": "8", }, { "activation": "high", "momentary": None, "name": "Konnected 445566 Actuator out1", "pause": None, "repeat": None, "state": None, "zone": "out1", }, { "activation": "high", "momentary": None, "name": "Konnected 445566 Actuator alarm1", "pause": None, "repeat": None, "state": None, "zone": "alarm1", }, ], } }