1 """Support for reading data from a serial port."""
3 from __future__
import annotations
9 from serial
import SerialException
10 import serial_asyncio_fast
as serial_asyncio
11 import voluptuous
as vol
14 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
23 _LOGGER = logging.getLogger(__name__)
25 CONF_SERIAL_PORT =
"serial_port"
26 CONF_BAUDRATE =
"baudrate"
27 CONF_BYTESIZE =
"bytesize"
28 CONF_PARITY =
"parity"
29 CONF_STOPBITS =
"stopbits"
30 CONF_XONXOFF =
"xonxoff"
31 CONF_RTSCTS =
"rtscts"
32 CONF_DSRDTR =
"dsrdtr"
34 DEFAULT_NAME =
"Serial Sensor"
35 DEFAULT_BAUDRATE = 9600
36 DEFAULT_BYTESIZE = serial_asyncio.serial.EIGHTBITS
37 DEFAULT_PARITY = serial_asyncio.serial.PARITY_NONE
38 DEFAULT_STOPBITS = serial_asyncio.serial.STOPBITS_ONE
39 DEFAULT_XONXOFF =
False
40 DEFAULT_RTSCTS =
False
41 DEFAULT_DSRDTR =
False
43 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
45 vol.Required(CONF_SERIAL_PORT): cv.string,
46 vol.Optional(CONF_BAUDRATE, default=DEFAULT_BAUDRATE): cv.positive_int,
47 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
48 vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
49 vol.Optional(CONF_BYTESIZE, default=DEFAULT_BYTESIZE): vol.In(
51 serial_asyncio.serial.FIVEBITS,
52 serial_asyncio.serial.SIXBITS,
53 serial_asyncio.serial.SEVENBITS,
54 serial_asyncio.serial.EIGHTBITS,
57 vol.Optional(CONF_PARITY, default=DEFAULT_PARITY): vol.In(
59 serial_asyncio.serial.PARITY_NONE,
60 serial_asyncio.serial.PARITY_EVEN,
61 serial_asyncio.serial.PARITY_ODD,
62 serial_asyncio.serial.PARITY_MARK,
63 serial_asyncio.serial.PARITY_SPACE,
66 vol.Optional(CONF_STOPBITS, default=DEFAULT_STOPBITS): vol.In(
68 serial_asyncio.serial.STOPBITS_ONE,
69 serial_asyncio.serial.STOPBITS_ONE_POINT_FIVE,
70 serial_asyncio.serial.STOPBITS_TWO,
73 vol.Optional(CONF_XONXOFF, default=DEFAULT_XONXOFF): cv.boolean,
74 vol.Optional(CONF_RTSCTS, default=DEFAULT_RTSCTS): cv.boolean,
75 vol.Optional(CONF_DSRDTR, default=DEFAULT_DSRDTR): cv.boolean,
83 async_add_entities: AddEntitiesCallback,
84 discovery_info: DiscoveryInfoType |
None =
None,
86 """Set up the Serial sensor platform."""
87 name = config.get(CONF_NAME)
88 port = config.get(CONF_SERIAL_PORT)
89 baudrate = config.get(CONF_BAUDRATE)
90 bytesize = config.get(CONF_BYTESIZE)
91 parity = config.get(CONF_PARITY)
92 stopbits = config.get(CONF_STOPBITS)
93 xonxoff = config.get(CONF_XONXOFF)
94 rtscts = config.get(CONF_RTSCTS)
95 dsrdtr = config.get(CONF_DSRDTR)
96 value_template = config.get(CONF_VALUE_TEMPLATE)
111 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, sensor.stop_serial_read)
116 """Representation of a Serial sensor."""
118 _attr_should_poll =
False
133 """Initialize the Serial sensor."""
149 """Handle when an entity is about to be added to Home Assistant."""
175 """Read the data from the port."""
179 reader, _ = await serial_asyncio.open_serial_connection(
191 except SerialException:
194 "Unable to connect to the serial device %s. Will retry", device
199 _LOGGER.debug(
"Serial device %s connected", device)
202 line = await reader.readline()
203 except SerialException:
205 "Error while reading serial device %s", device
210 line = line.decode(
"utf-8").strip()
213 data = json.loads(line)
217 if isinstance(data, dict):
221 line = self.
_template_template.async_render_with_possible_json_value(
225 _LOGGER.debug(
"Received: %s", line)
230 """Handle error for serial connection."""
234 await asyncio.sleep(5)
238 """Close resources."""
244 """Return the name of the sensor."""
245 return self.
_name_name
249 """Return the attributes of the entity (if any JSON present)."""
254 """Return the state of the sensor."""
def __init__(self, name, port, baudrate, bytesize, parity, stopbits, xonxoff, rtscts, dsrdtr, value_template)
def serial_read(self, device, baudrate, bytesize, parity, stopbits, xonxoff, rtscts, dsrdtr, **kwargs)
def stop_serial_read(self, event)
None async_added_to_hass(self)
def extra_state_attributes(self)
None async_write_ha_state(self)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)