mirror of
https://github.com/esphome/esphome.git
synced 2026-10-09 04:16:01 +00:00
[sendspin] Add the dynamic pairing code (#20349)
This commit is contained in:
@@ -9,7 +9,12 @@ from typing import Any
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.sendspin import CONF_STATIC_PAIRING_CODE, CONFIG_SCHEMA
|
||||
from esphome.components.sendspin import (
|
||||
CONF_STATIC_PAIRING_CODE,
|
||||
CONFIG_SCHEMA,
|
||||
FINAL_VALIDATE_SCHEMA,
|
||||
request_pairing_code_display_support,
|
||||
)
|
||||
from esphome.const import PlatformFramework
|
||||
from esphome.types import ConfigType
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
@@ -75,3 +80,16 @@ def test_unquoted_static_pairing_code_rejected(
|
||||
|
||||
with pytest.raises(cv.Invalid):
|
||||
CONFIG_SCHEMA(_hub_config(static_pairing_code=1234567))
|
||||
|
||||
|
||||
def test_static_code_with_dynamic_code_rejected(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""Only one pairing code method can be offered, so a static code next to the dynamic
|
||||
code would be silently ignored."""
|
||||
set_core_config(PlatformFramework.ESP32_IDF)
|
||||
request_pairing_code_display_support()
|
||||
config = CONFIG_SCHEMA(_hub_config(static_pairing_code="01234567"))
|
||||
|
||||
with pytest.raises(cv.Invalid, match="cannot be used with a dynamic pairing code"):
|
||||
FINAL_VALIDATE_SCHEMA(config)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
"""Validation tests for the sendspin text sensor platform.
|
||||
|
||||
These cover behavior a compile test cannot observe: which roles a sensor type requests.
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import config_validation as cv
|
||||
from esphome.components.sendspin import _get_data
|
||||
from esphome.components.sendspin.text_sensor import (
|
||||
CONF_PAIRING_CODE,
|
||||
CONFIG_SCHEMA,
|
||||
SENDSPIN_TEXT_METADATA_TYPES,
|
||||
)
|
||||
from esphome.const import PlatformFramework
|
||||
from esphome.types import ConfigType
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def _sensor_config(**overrides: Any) -> ConfigType:
|
||||
"""Build a minimal valid text sensor config, allowing field overrides."""
|
||||
config: ConfigType = {"name": "Sendspin Text", "type": "title"}
|
||||
config.update(overrides)
|
||||
return config
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sensor_type", sorted(SENDSPIN_TEXT_METADATA_TYPES))
|
||||
def test_metadata_types_request_metadata_role(
|
||||
set_core_config: SetCoreConfigCallable, sensor_type: str
|
||||
) -> None:
|
||||
"""Metadata sensors need the metadata role, and say nothing about pairing codes."""
|
||||
set_core_config(PlatformFramework.ESP32_IDF)
|
||||
|
||||
CONFIG_SCHEMA(_sensor_config(type=sensor_type))
|
||||
|
||||
assert _get_data().metadata_support is True
|
||||
assert _get_data().pairing_code_display_support is False
|
||||
|
||||
|
||||
def test_pairing_code_requests_code_display(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A pairing_code sensor is a way to show the dynamic code, so it alone makes the
|
||||
hub offer it. It needs no role, so a pairing-only config builds without metadata."""
|
||||
set_core_config(PlatformFramework.ESP32_IDF)
|
||||
|
||||
CONFIG_SCHEMA(_sensor_config(type=CONF_PAIRING_CODE))
|
||||
|
||||
assert _get_data().pairing_code_display_support is True
|
||||
assert _get_data().metadata_support is False
|
||||
|
||||
|
||||
def test_unknown_type_rejected(set_core_config: SetCoreConfigCallable) -> None:
|
||||
"""A misspelled type must fail rather than fall through to a default."""
|
||||
set_core_config(PlatformFramework.ESP32_IDF)
|
||||
|
||||
with pytest.raises(cv.Invalid):
|
||||
CONFIG_SCHEMA(_sensor_config(type="pairing_secret"))
|
||||
@@ -8,6 +8,7 @@ from esphome.components.sendspin import (
|
||||
CONF_UNPAIRED_ACCESS,
|
||||
CONFIG_SCHEMA as HUB_CONFIG_SCHEMA,
|
||||
FINAL_VALIDATE_SCHEMA as HUB_FINAL_VALIDATE_SCHEMA,
|
||||
request_pairing_code_display_support,
|
||||
)
|
||||
from esphome.const import PlatformFramework
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
@@ -45,7 +46,7 @@ def test_off_without_pairing_method_warns(
|
||||
assert NO_PAIRING_WARNING in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("method", ["static_pairing_code"])
|
||||
@pytest.mark.parametrize("method", ["static_pairing_code", "pairing_code"])
|
||||
def test_off_with_pairing_method_does_not_warn(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
@@ -55,6 +56,8 @@ def test_off_with_pairing_method_does_not_warn(
|
||||
hub_config = {"id": HUB_ID, CONF_UNPAIRED_ACCESS: False}
|
||||
if method == "static_pairing_code":
|
||||
hub_config["static_pairing_code"] = "01234567"
|
||||
else:
|
||||
request_pairing_code_display_support()
|
||||
config = HUB_CONFIG_SCHEMA(hub_config)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
|
||||
@@ -7,6 +7,9 @@ sendspin:
|
||||
manufacturer: Test Manufacturer
|
||||
model: Test Model
|
||||
firmware_version: 1.2.3
|
||||
# No static_pairing_code here: the on_display_pairing_code automation below makes
|
||||
# this a dynamic-pairing-code device, and validation rejects both together.
|
||||
# common-pairing.yaml covers the static-code build.
|
||||
on_open_pairing_window:
|
||||
then:
|
||||
- logger.log: "Pairing window requested"
|
||||
@@ -16,6 +19,14 @@ sendspin:
|
||||
then:
|
||||
- logger.log: "Pairing window prompt dismissed"
|
||||
- sendspin.cancel_pairing_window:
|
||||
on_display_pairing_code:
|
||||
then:
|
||||
- logger.log:
|
||||
format: "Pairing code: %s"
|
||||
args: ["code.c_str()"]
|
||||
on_clear_pairing_code:
|
||||
then:
|
||||
- logger.log: "Pairing code cleared"
|
||||
on_pairing_succeeded:
|
||||
then:
|
||||
- logger.log:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# The pairing code text sensor on its own, with no metadata text sensor to pull in the
|
||||
# metadata role. This is the build where USE_SENDSPIN_METADATA is undefined while the text
|
||||
# sensor platform is still compiled, which is guarded separately in sendspin_text_sensor.{h,cpp}.
|
||||
#
|
||||
# Deliberately does not include common.yaml: that file pulls in the shared hub package, and
|
||||
# the point here is the narrower configuration. sendspin depends on network, so the interface
|
||||
# has to be declared locally instead.
|
||||
wifi:
|
||||
ap:
|
||||
|
||||
sendspin:
|
||||
id: sendspin_hub_id
|
||||
|
||||
text_sensor:
|
||||
- platform: sendspin
|
||||
name: "Pairing Code"
|
||||
type: pairing_code
|
||||
@@ -14,3 +14,7 @@ text_sensor:
|
||||
- platform: sendspin
|
||||
name: "Album Artist"
|
||||
type: album_artist
|
||||
- platform: sendspin
|
||||
name: "Pairing Code"
|
||||
type: pairing_code
|
||||
entity_category: diagnostic
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
sendspin: !include common-text_sensor-pairing.yaml
|
||||
Reference in New Issue
Block a user