Fix MQTT camera encoding (#76124)
* Fix MQTT camera encoding * Reduce code * Add test for using image_encoding parameter * Move deprecation check to validation * Dependency * Set correct strings and log warning * Rename constant * Use better issue string identifier * Revert unwanted change to hassio test * Avoid term `deprecated` in issue description * Revert changes using the repairs API * Add a notice when work-a-round will be removed * Update homeassistant/components/mqtt/camera.py Co-authored-by: Erik Montnemery <erik@montnemery.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>pull/76786/head
parent
4f9e6d2407
commit
f72cfef7be
|
@ -80,6 +80,7 @@ ABBREVIATIONS = {
|
|||
"hs_stat_t": "hs_state_topic",
|
||||
"hs_val_tpl": "hs_value_template",
|
||||
"ic": "icon",
|
||||
"img_e": "image_encoding",
|
||||
"init": "initial",
|
||||
"hum_cmd_t": "target_humidity_command_topic",
|
||||
"hum_cmd_tpl": "target_humidity_command_template",
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||
|
||||
from base64 import b64decode
|
||||
import functools
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -17,7 +18,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|||
|
||||
from . import subscription
|
||||
from .config import MQTT_BASE_SCHEMA
|
||||
from .const import CONF_ENCODING, CONF_QOS, CONF_TOPIC
|
||||
from .const import CONF_ENCODING, CONF_QOS, CONF_TOPIC, DEFAULT_ENCODING
|
||||
from .debug_info import log_messages
|
||||
from .mixins import (
|
||||
MQTT_ENTITY_COMMON_SCHEMA,
|
||||
|
@ -29,6 +30,10 @@ from .mixins import (
|
|||
)
|
||||
from .util import valid_subscribe_topic
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_IMAGE_ENCODING = "image_encoding"
|
||||
|
||||
DEFAULT_NAME = "MQTT Camera"
|
||||
|
||||
MQTT_CAMERA_ATTRIBUTES_BLOCKED = frozenset(
|
||||
|
@ -40,20 +45,41 @@ MQTT_CAMERA_ATTRIBUTES_BLOCKED = frozenset(
|
|||
}
|
||||
)
|
||||
|
||||
PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||
|
||||
# Using CONF_ENCODING to set b64 encoding for images is deprecated as of Home Assistant 2022.9
|
||||
# use CONF_IMAGE_ENCODING instead, support for the work-a-round will be removed with Home Assistant 2022.11
|
||||
def repair_legacy_encoding(config: ConfigType) -> ConfigType:
|
||||
"""Check incorrect deprecated config of image encoding."""
|
||||
if config[CONF_ENCODING] == "b64":
|
||||
config[CONF_IMAGE_ENCODING] = "b64"
|
||||
config[CONF_ENCODING] = DEFAULT_ENCODING
|
||||
_LOGGER.warning(
|
||||
"Using the `encoding` parameter to set image encoding has been deprecated, use `image_encoding` instead"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Required(CONF_TOPIC): valid_subscribe_topic,
|
||||
vol.Optional(CONF_IMAGE_ENCODING): "b64",
|
||||
}
|
||||
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
||||
|
||||
# Configuring MQTT Camera under the camera platform key is deprecated in HA Core 2022.6
|
||||
PLATFORM_SCHEMA = vol.All(
|
||||
cv.PLATFORM_SCHEMA.extend(PLATFORM_SCHEMA_MODERN.schema),
|
||||
warn_for_legacy_schema(camera.DOMAIN),
|
||||
PLATFORM_SCHEMA_MODERN = vol.All(
|
||||
PLATFORM_SCHEMA_BASE.schema,
|
||||
repair_legacy_encoding,
|
||||
)
|
||||
|
||||
DISCOVERY_SCHEMA = PLATFORM_SCHEMA_MODERN.extend({}, extra=vol.REMOVE_EXTRA)
|
||||
# Configuring MQTT Camera under the camera platform key is deprecated in HA Core 2022.6
|
||||
PLATFORM_SCHEMA = vol.All(
|
||||
cv.PLATFORM_SCHEMA.extend(PLATFORM_SCHEMA_BASE.schema),
|
||||
warn_for_legacy_schema(camera.DOMAIN),
|
||||
repair_legacy_encoding,
|
||||
)
|
||||
|
||||
DISCOVERY_SCHEMA = PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
|
@ -124,7 +150,7 @@ class MqttCamera(MqttEntity, Camera):
|
|||
@log_messages(self.hass, self.entity_id)
|
||||
def message_received(msg):
|
||||
"""Handle new MQTT messages."""
|
||||
if self._config[CONF_ENCODING] == "b64":
|
||||
if CONF_IMAGE_ENCODING in self._config:
|
||||
self._last_image = b64decode(msg.payload)
|
||||
else:
|
||||
self._last_image = msg.payload
|
||||
|
|
|
@ -110,6 +110,80 @@ async def test_run_camera_b64_encoded(
|
|||
assert body == "grass"
|
||||
|
||||
|
||||
# Using CONF_ENCODING to set b64 encoding for images is deprecated Home Assistant 2022.9, use CONF_IMAGE_ENCODING instead
|
||||
async def test_legacy_camera_b64_encoded_with_availability(
|
||||
hass, hass_client_no_auth, mqtt_mock_entry_with_yaml_config
|
||||
):
|
||||
"""Test availability works if b64 encoding (legacy mode) is turned on."""
|
||||
topic = "test/camera"
|
||||
topic_availability = "test/camera_availability"
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"camera",
|
||||
{
|
||||
"camera": {
|
||||
"platform": "mqtt",
|
||||
"topic": topic,
|
||||
"name": "Test Camera",
|
||||
"encoding": "b64",
|
||||
"availability": {"topic": topic_availability},
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await mqtt_mock_entry_with_yaml_config()
|
||||
|
||||
# Make sure we are available
|
||||
async_fire_mqtt_message(hass, topic_availability, "online")
|
||||
|
||||
url = hass.states.get("camera.test_camera").attributes["entity_picture"]
|
||||
|
||||
async_fire_mqtt_message(hass, topic, b64encode(b"grass"))
|
||||
|
||||
client = await hass_client_no_auth()
|
||||
resp = await client.get(url)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
body = await resp.text()
|
||||
assert body == "grass"
|
||||
|
||||
|
||||
async def test_camera_b64_encoded_with_availability(
|
||||
hass, hass_client_no_auth, mqtt_mock_entry_with_yaml_config
|
||||
):
|
||||
"""Test availability works if b64 encoding is turned on."""
|
||||
topic = "test/camera"
|
||||
topic_availability = "test/camera_availability"
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"camera",
|
||||
{
|
||||
"camera": {
|
||||
"platform": "mqtt",
|
||||
"topic": topic,
|
||||
"name": "Test Camera",
|
||||
"encoding": "utf-8",
|
||||
"image_encoding": "b64",
|
||||
"availability": {"topic": topic_availability},
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await mqtt_mock_entry_with_yaml_config()
|
||||
|
||||
# Make sure we are available
|
||||
async_fire_mqtt_message(hass, topic_availability, "online")
|
||||
|
||||
url = hass.states.get("camera.test_camera").attributes["entity_picture"]
|
||||
|
||||
async_fire_mqtt_message(hass, topic, b64encode(b"grass"))
|
||||
|
||||
client = await hass_client_no_auth()
|
||||
resp = await client.get(url)
|
||||
assert resp.status == HTTPStatus.OK
|
||||
body = await resp.text()
|
||||
assert body == "grass"
|
||||
|
||||
|
||||
async def test_availability_when_connection_lost(
|
||||
hass, mqtt_mock_entry_with_yaml_config
|
||||
):
|
||||
|
|
Loading…
Reference in New Issue