Add partial mobile app sensor validation (#36433)
parent
8528b4db3a
commit
68b077ffaa
homeassistant/components/mobile_app
tests/components/mobile_app
|
@ -57,6 +57,7 @@ ERR_ENCRYPTION_NOT_AVAILABLE = "encryption_not_available"
|
|||
ERR_ENCRYPTION_REQUIRED = "encryption_required"
|
||||
ERR_SENSOR_NOT_REGISTERED = "not_registered"
|
||||
ERR_SENSOR_DUPLICATE_UNIQUE_ID = "duplicate_unique_id"
|
||||
ERR_INVALID_FORMAT = "invalid_format"
|
||||
|
||||
|
||||
ATTR_SENSOR_ATTRIBUTES = "attributes"
|
||||
|
|
|
@ -76,6 +76,7 @@ from .const import (
|
|||
ERR_ENCRYPTION_ALREADY_ENABLED,
|
||||
ERR_ENCRYPTION_NOT_AVAILABLE,
|
||||
ERR_ENCRYPTION_REQUIRED,
|
||||
ERR_INVALID_FORMAT,
|
||||
ERR_SENSOR_DUPLICATE_UNIQUE_ID,
|
||||
ERR_SENSOR_NOT_REGISTERED,
|
||||
SIGNAL_LOCATION_UPDATE,
|
||||
|
@ -394,20 +395,31 @@ async def webhook_register_sensor(hass, config_entry, data):
|
|||
vol.All(
|
||||
cv.ensure_list,
|
||||
[
|
||||
# Partial schema, enough to identify schema.
|
||||
# We don't validate everything because otherwise 1 invalid sensor
|
||||
# will invalidate all sensors.
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_SENSOR_ATTRIBUTES, default={}): dict,
|
||||
vol.Optional(ATTR_SENSOR_ICON, default="mdi:cellphone"): cv.icon,
|
||||
vol.Required(ATTR_SENSOR_STATE): vol.Any(bool, str, int, float),
|
||||
vol.Required(ATTR_SENSOR_TYPE): vol.In(SENSOR_TYPES),
|
||||
vol.Required(ATTR_SENSOR_UNIQUE_ID): cv.string,
|
||||
}
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
async def webhook_update_sensor_states(hass, config_entry, data):
|
||||
"""Handle an update sensor states webhook."""
|
||||
sensor_schema_full = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_SENSOR_ATTRIBUTES, default={}): dict,
|
||||
vol.Optional(ATTR_SENSOR_ICON, default="mdi:cellphone"): cv.icon,
|
||||
vol.Required(ATTR_SENSOR_STATE): vol.Any(bool, str, int, float),
|
||||
vol.Required(ATTR_SENSOR_TYPE): vol.In(SENSOR_TYPES),
|
||||
vol.Required(ATTR_SENSOR_UNIQUE_ID): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
resp = {}
|
||||
for sensor in data:
|
||||
entity_type = sensor[ATTR_SENSOR_TYPE]
|
||||
|
@ -429,6 +441,19 @@ async def webhook_update_sensor_states(hass, config_entry, data):
|
|||
|
||||
entry = hass.data[DOMAIN][entity_type][unique_store_key]
|
||||
|
||||
try:
|
||||
sensor = sensor_schema_full(sensor)
|
||||
except vol.Invalid as err:
|
||||
err_msg = vol.humanize.humanize_error(sensor, err)
|
||||
_LOGGER.error(
|
||||
"Received invalid sensor payload for %s: %s", unique_id, err_msg
|
||||
)
|
||||
resp[unique_id] = {
|
||||
"success": False,
|
||||
"error": {"code": ERR_INVALID_FORMAT, "message": err_msg},
|
||||
}
|
||||
continue
|
||||
|
||||
new_state = {**entry, **sensor}
|
||||
|
||||
hass.data[DOMAIN][entity_type][unique_store_key] = new_state
|
||||
|
|
|
@ -57,13 +57,18 @@ async def test_sensor(hass, create_registrations, webhook_client):
|
|||
"state": 123,
|
||||
"type": "sensor",
|
||||
"unique_id": "battery_state",
|
||||
}
|
||||
},
|
||||
# This invalid data should not invalidate whole request
|
||||
{"type": "sensor", "unique_id": "invalid_state", "invalid": "data"},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert update_resp.status == 200
|
||||
|
||||
json = await update_resp.json()
|
||||
assert json["invalid_state"]["success"] is False
|
||||
|
||||
updated_entity = hass.states.get("sensor.test_1_battery_state")
|
||||
assert updated_entity.state == "123"
|
||||
|
||||
|
|
Loading…
Reference in New Issue