async def test_ssdp_host_update(opp, 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_opp(opp) mock_panel.get_status.return_value = { "mac": "11:22:33:44:55:66", "model": "Konnected Pro", } result = await opp.config_entries.flow.async_init( config_flow.DOMAIN, context={"source": config_entries.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 = opp.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(opp, 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_opp(opp) result = await opp.config_entries.options.async_init( entry.entry_id, context={"source": "test"}) assert result["type"] == "form" assert result["step_id"] == "options_io" result = await opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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_option_flow_import(opp, 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_opp(opp) result = await opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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_existing(opp, 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_opp(opp) result = await opp.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_option_flow_pro(opp, 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_opp(opp) result = await opp.config_entries.options.async_init( entry.entry_id, context={"source": "test"}) assert result["type"] == "form" assert result["step_id"] == "options_io" result = await opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.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 opp.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone 8 result = await opp.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 opp.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_switch" # zone alarm1 result = await opp.config_entries.options.async_configure( result["flow_id"], user_input={}) assert result["type"] == "form" assert result["step_id"] == "options_misc" result = await opp.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_state_updates_pin(opp, aiohttp_client, mock_panel): """Test callback view.""" await async_process_op_core_config( opp, {"internal_url": "http://example.local:8123"}, ) device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected", "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_opp(opp) # 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_opp(opp) assert (await async_setup_component( opp, konnected.DOMAIN, {konnected.DOMAIN: { konnected.CONF_ACCESS_TOKEN: "1122334455" }}, ) is True) client = await aiohttp_client(opp.http.app) # Test updating a binary sensor resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "pin": "1", "state": 0 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.states.get( "binary_sensor.konnected_445566_zone_1").state == "off" resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "pin": "1", "state": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.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={ "pin": "6", "temp": 22, "humi": 20 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.states.get( "sensor.konnected_445566_sensor_4_humidity").state == "20" assert (opp.states.get( "sensor.konnected_445566_sensor_4_temperature").state == "22.0") resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "pin": "6", "temp": 25, "humi": 23 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.states.get( "sensor.konnected_445566_sensor_4_humidity").state == "23" assert (opp.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={ "pin": "7", "temp": 32, "addr": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.states.get("sensor.temper_temperature").state == "32.0" resp = await client.post( "/api/konnected/device/112233445566", headers={"Authorization": "Bearer abcdefgh"}, json={ "pin": "7", "temp": 42, "addr": 1 }, ) assert resp.status == 200 result = await resp.json() assert result == {"message": "ok"} await opp.async_block_till_done() assert opp.states.get("sensor.temper_temperature").state == "42.0"
async def test_api(opp, aiohttp_client, mock_panel): """Test callback view.""" await async_setup_component(opp, "http", {"http": {}}) device_config = config_flow.CONFIG_ENTRY_SCHEMA({ "host": "1.2.3.4", "port": 1234, "id": "112233445566", "model": "Konnected Pro", "access_token": "abcdefgh", "api_host": "http://192.168.86.32:8123", "default_options": config_flow.OPTIONS_SCHEMA({config_flow.CONF_IO: {}}), }) device_options = config_flow.OPTIONS_SCHEMA({ "api_host": "http://192.168.86.32:8123", "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_opp(opp) assert (await async_setup_component( opp, konnected.DOMAIN, {konnected.DOMAIN: { konnected.CONF_ACCESS_TOKEN: "globaltoken" }}, ) is True) client = await aiohttp_client(opp.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_connect_retry(opp, 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_opp(opp) # 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( opp, 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 opp.async_block_till_done() assert opp.states.get( "switch.konnected_445566_actuator_6").state == "unavailable" # confirm switch is unavailable after second attempt async_fire_time_changed(opp, utcnow() + timedelta(seconds=11)) await opp.async_block_till_done() await opp.helpers.entity_component.async_update_entity( "switch.konnected_445566_actuator_6") assert opp.states.get( "switch.konnected_445566_actuator_6").state == "unavailable" # confirm switch is available after third attempt async_fire_time_changed(opp, utcnow() + timedelta(seconds=21)) await opp.async_block_till_done() await opp.helpers.entity_component.async_update_entity( "switch.konnected_445566_actuator_6") assert opp.states.get("switch.konnected_445566_actuator_6").state == "off"
async def test_default_options(opp, 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_opp(opp) # 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( opp, 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. # opp.data is the only mechanism to get a reference to the created panel instance device = opp.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 opp.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", }, ], }