1 """Allows to configure custom shell commands to turn a value for a sensor."""
3 from __future__
import annotations
6 from collections.abc
import Mapping
7 from datetime
import datetime, timedelta
9 from typing
import Any, cast
11 from jsonpath
import jsonpath
33 CONF_JSON_ATTRIBUTES_PATH,
35 TRIGGER_ENTITY_OPTIONS,
37 from .utils
import async_check_output_or_log
39 DEFAULT_NAME =
"Command Sensor"
47 async_add_entities: AddEntitiesCallback,
48 discovery_info: DiscoveryInfoType |
None =
None,
50 """Set up the Command Sensor."""
51 if not discovery_info:
54 discovery_info = cast(DiscoveryInfoType, discovery_info)
55 sensor_config = discovery_info
57 command: str = sensor_config[CONF_COMMAND]
58 command_timeout: int = sensor_config[CONF_COMMAND_TIMEOUT]
59 json_attributes: list[str] |
None = sensor_config.get(CONF_JSON_ATTRIBUTES)
60 json_attributes_path: str |
None = sensor_config.get(CONF_JSON_ATTRIBUTES_PATH)
61 scan_interval: timedelta = sensor_config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL)
62 value_template: Template |
None = sensor_config.get(CONF_VALUE_TEMPLATE)
65 trigger_entity_config = {
66 CONF_NAME:
Template(sensor_config[CONF_NAME], hass),
67 **{k: v
for k, v
in sensor_config.items()
if k
in TRIGGER_ENTITY_OPTIONS},
74 trigger_entity_config,
85 """Representation of a sensor that is using shell commands."""
87 _attr_should_poll =
False
91 data: CommandSensorData,
93 value_template: Template |
None,
94 json_attributes: list[str] |
None,
95 json_attributes_path: str |
None,
96 scan_interval: timedelta,
98 """Initialize the sensor."""
111 """Return extra state attributes."""
115 """Call when entity about to be added to hass."""
123 name=f
"Command Line Sensor - {self.name}",
124 cancel_on_shutdown=
True,
129 """Update the state of the entity."""
135 "Updating Command Line Sensor %s took longer than the scheduled update interval %s",
145 """Get the latest data and updates the state."""
147 value = self.
datadata.value
153 json_dict = json.loads(value)
159 if isinstance(json_dict, list):
160 json_dict = json_dict[0]
161 if isinstance(json_dict, Mapping):
168 LOGGER.warning(
"JSON result was not a dictionary")
170 LOGGER.warning(
"Unable to parse output as JSON: %s", value)
172 LOGGER.warning(
"Empty reply found when expecting JSON data")
179 if self.
_value_template_value_template
is not None and value
is not None:
180 value = self.
_value_template_value_template.async_render_with_possible_json_value(
186 SensorDeviceClass.DATE,
187 SensorDeviceClass.TIMESTAMP,
190 elif value
is not None:
199 """Update the entity.
201 Only used by the generic entity update service.
207 """The class for handling the data retrieval."""
209 def __init__(self, hass: HomeAssistant, command: str, command_timeout: int) ->
None:
210 """Initialize the data object."""
211 self.
valuevalue: str |
None =
None
217 """Get the latest data with a shell command."""
220 if " " not in command:
225 prog, args = command.split(
" ", 1)
230 args_to_render = {
"arguments": args}
231 rendered_args = args_compiled.async_render(args_to_render)
232 except TemplateError
as ex:
233 LOGGER.exception(
"Error rendering command template: %s", ex)
238 if rendered_args == args:
243 command = f
"{prog} {rendered_args}"
245 LOGGER.debug(
"Running command: %s", command)
None __init__(self, HomeAssistant hass, str command, int command_timeout)
None __init__(self, CommandSensorData data, ConfigType config, Template|None value_template, list[str]|None json_attributes, str|None json_attributes_path, timedelta scan_interval)
None _update_entity_state(self, datetime|None now=None)
None async_added_to_hass(self)
_attr_extra_state_attributes
dict[str, Any] extra_state_attributes(self)
SensorDeviceClass|None device_class(self)
str|None device_class(self)
None async_write_ha_state(self)
None async_on_remove(self, CALLBACK_TYPE func)
str|UndefinedType|None name(self)
None _process_manual_data(self, Any|None value=None)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
str|None async_check_output_or_log(str command, int timeout)
datetime|date|None async_parse_date_datetime(str value, str entity_id, SensorDeviceClass|str|None device_class)
CALLBACK_TYPE async_track_time_interval(HomeAssistant hass, Callable[[datetime], Coroutine[Any, Any, None]|None] action, timedelta interval, *str|None name=None, bool|None cancel_on_shutdown=None)