mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 05:37:44 +00:00
Add mysensors text platform (#84667)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
c0da80b567
commit
5d4216d648
@ -135,6 +135,7 @@ SWITCH_TYPES: dict[SensorType, set[ValueType]] = {
|
||||
"S_WATER_QUALITY": {"V_STATUS"},
|
||||
}
|
||||
|
||||
TEXT_TYPES: dict[SensorType, set[ValueType]] = {"S_INFO": {"V_TEXT"}}
|
||||
|
||||
PLATFORM_TYPES: dict[Platform, dict[SensorType, set[ValueType]]] = {
|
||||
Platform.BINARY_SENSOR: BINARY_SENSOR_TYPES,
|
||||
@ -145,6 +146,7 @@ PLATFORM_TYPES: dict[Platform, dict[SensorType, set[ValueType]]] = {
|
||||
Platform.NOTIFY: NOTIFY_TYPES,
|
||||
Platform.SENSOR: SENSOR_TYPES,
|
||||
Platform.SWITCH: SWITCH_TYPES,
|
||||
Platform.TEXT: TEXT_TYPES,
|
||||
}
|
||||
|
||||
FLAT_PLATFORM_TYPES: dict[tuple[str, SensorType], set[ValueType]] = {
|
||||
|
@ -6,10 +6,12 @@ from typing import Any, cast
|
||||
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .. import mysensors
|
||||
from .const import DevId, DiscoveryInfo
|
||||
from .const import DOMAIN, DevId, DiscoveryInfo
|
||||
|
||||
|
||||
async def async_get_service(
|
||||
@ -63,6 +65,7 @@ class MySensorsNotificationService(BaseNotificationService):
|
||||
] = mysensors.get_mysensors_devices(
|
||||
hass, Platform.NOTIFY
|
||||
) # type: ignore[assignment]
|
||||
self.hass = hass
|
||||
|
||||
async def async_send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||
"""Send a message to a user."""
|
||||
@ -73,5 +76,25 @@ class MySensorsNotificationService(BaseNotificationService):
|
||||
if target_devices is None or device.name in target_devices
|
||||
]
|
||||
|
||||
placeholders = {
|
||||
"alternate_service": "text.set_value",
|
||||
"deprecated_service": f"notify.{self._service_name}",
|
||||
"alternate_target": str(
|
||||
[f"text.{slugify(device.name)}" for device in devices]
|
||||
),
|
||||
}
|
||||
|
||||
async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
"deprecated_notify_service",
|
||||
breaks_in_ha_version="2023.4.0",
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_service",
|
||||
translation_placeholders=placeholders,
|
||||
)
|
||||
|
||||
for device in devices:
|
||||
device.send_msg(message)
|
||||
|
@ -83,5 +83,18 @@
|
||||
"port_out_of_range": "Port number must be at least 1 and at most 65535",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_service": {
|
||||
"title": "The {deprecated_service} service will be removed",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "The {deprecated_service} service will be removed",
|
||||
"description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with a target entity ID of `{alternate_target}`."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
60
homeassistant/components/mysensors/text.py
Normal file
60
homeassistant/components/mysensors/text.py
Normal file
@ -0,0 +1,60 @@
|
||||
"""Provide a text platform for MySensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.text import TextEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .. import mysensors
|
||||
from .const import MYSENSORS_DISCOVERY, DiscoveryInfo
|
||||
from .device import MySensorsEntity
|
||||
from .helpers import on_unload
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up this platform for a specific ConfigEntry(==Gateway)."""
|
||||
|
||||
@callback
|
||||
def async_discover(discovery_info: DiscoveryInfo) -> None:
|
||||
"""Discover and add a MySensors text entity."""
|
||||
mysensors.setup_mysensors_platform(
|
||||
hass,
|
||||
Platform.TEXT,
|
||||
discovery_info,
|
||||
MySensorsText,
|
||||
async_add_entities=async_add_entities,
|
||||
)
|
||||
|
||||
on_unload(
|
||||
hass,
|
||||
config_entry.entry_id,
|
||||
async_dispatcher_connect(
|
||||
hass,
|
||||
MYSENSORS_DISCOVERY.format(config_entry.entry_id, Platform.TEXT),
|
||||
async_discover,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class MySensorsText(MySensorsEntity, TextEntity):
|
||||
"""Representation of the value of a MySensors Text child node."""
|
||||
|
||||
_attr_native_max = 25
|
||||
|
||||
@property
|
||||
def native_value(self) -> str | None:
|
||||
"""Return the value reported by the text."""
|
||||
return self._values.get(self.value_type)
|
||||
|
||||
async def async_set_value(self, value: str) -> None:
|
||||
"""Change the value."""
|
||||
self.gateway.set_child_value(
|
||||
self.node_id, self.child_id, self.value_type, value, ack=1
|
||||
)
|
@ -83,5 +83,18 @@
|
||||
"description": "Choose connection method to the gateway"
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_service": {
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with a target entity ID of `{alternate_target}`.",
|
||||
"title": "The {deprecated_service} service will be removed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "The {deprecated_service} service will be removed"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
tests/components/mysensors/test_text.py
Normal file
65
tests/components/mysensors/test_text.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""Provide tests for mysensors text platform."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from unittest.mock import MagicMock, call
|
||||
|
||||
from mysensors.sensor import Sensor
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.text import (
|
||||
ATTR_VALUE,
|
||||
DOMAIN as TEXT_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
async def test_text_node(
|
||||
hass: HomeAssistant,
|
||||
text_node: Sensor,
|
||||
receive_message: Callable[[str], None],
|
||||
transport_write: MagicMock,
|
||||
) -> None:
|
||||
"""Test a text node."""
|
||||
entity_id = "text.text_node_1_1"
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
|
||||
assert state
|
||||
assert state.state == "test"
|
||||
|
||||
await hass.services.async_call(
|
||||
TEXT_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_VALUE: "Hello World"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert transport_write.call_count == 1
|
||||
assert transport_write.call_args == call("1;1;1;1;47;Hello World\n")
|
||||
|
||||
receive_message("1;1;1;0;47;Hello World\n")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
|
||||
assert state
|
||||
assert state.state == "Hello World"
|
||||
|
||||
transport_write.reset_mock()
|
||||
|
||||
value = "12345678123456781234567812"
|
||||
|
||||
with pytest.raises(ValueError) as err:
|
||||
await hass.services.async_call(
|
||||
TEXT_DOMAIN,
|
||||
SERVICE_SET_VALUE,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert str(err.value) == (
|
||||
f"Value {value} for Text Node 1 1 is too long (maximum length 25)"
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user