1 """Code to handle a Firmata board."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
7 from typing
import Literal
9 from pymata_express.pymata_express
import PymataExpress
10 from pymata_express.pymata_express_serial
import serial
21 CONF_ARDUINO_INSTANCE_ID,
23 CONF_SAMPLING_INTERVAL,
24 CONF_SERIAL_BAUD_RATE,
31 _LOGGER = logging.getLogger(__name__)
33 type FirmataPinType = int | str
37 """Manages a single Firmata board."""
40 """Initialize the board."""
42 self.
apiapi: PymataExpress =
None
50 self.used_pins: list[FirmataPinType] = []
52 if CONF_SWITCHES
in self.
configconfig:
54 if CONF_LIGHTS
in self.
configconfig:
56 if CONF_BINARY_SENSORS
in self.
configconfig:
58 if CONF_SENSORS
in self.
configconfig:
62 """Set up a Firmata instance."""
64 _LOGGER.debug(
"Connecting to Firmata %s", self.
namename)
66 except RuntimeError
as err:
67 _LOGGER.error(
"Error connecting to PyMata board %s: %s", self.
namename, err)
69 except serial.SerialTimeoutException
as err:
71 "Timeout writing to serial port for PyMata board %s: %s", self.
namename, err
74 except serial.SerialException
as err:
76 "Error connecting to serial port for PyMata board %s: %s",
85 "Error retrieving firmware version from Firmata board %s", self.
namename
89 if CONF_SAMPLING_INTERVAL
in self.
configconfig:
91 await self.
apiapi.set_sampling_interval(
92 self.
configconfig[CONF_SAMPLING_INTERVAL]
94 except RuntimeError
as err:
96 "Error setting sampling interval for PyMata board %s: %s",
102 _LOGGER.debug(
"Firmata connection successful for %s", self.
namename)
106 """Reset the board to default state."""
107 _LOGGER.debug(
"Shutting down board %s", self.
namename)
109 if self.
apiapi
is None:
118 """Test if a pin is used already on the board or mark as used."""
119 if pin
in self.used_pins:
121 self.used_pins.append(pin)
124 def get_pin_type(self, pin: FirmataPinType) -> tuple[Literal[0, 1], int]:
125 """Return the type and Firmata location of a pin on the board."""
126 pin_type: Literal[0, 1]
128 if isinstance(pin, str):
129 pin_type = PIN_TYPE_ANALOG
130 firmata_pin =
int(pin[1:])
131 firmata_pin += self.
apiapi.first_analog_pin
133 pin_type = PIN_TYPE_DIGITAL
135 return (pin_type, firmata_pin)
139 """Create a Pymata board object."""
142 if CONF_SERIAL_PORT
in data:
143 board_data[
"com_port"] = data[CONF_SERIAL_PORT]
144 if CONF_SERIAL_BAUD_RATE
in data:
145 board_data[
"baud_rate"] = data[CONF_SERIAL_BAUD_RATE]
146 if CONF_ARDUINO_INSTANCE_ID
in data:
147 board_data[
"arduino_instance_id"] = data[CONF_ARDUINO_INSTANCE_ID]
149 if CONF_ARDUINO_WAIT
in data:
150 board_data[
"arduino_wait"] = data[CONF_ARDUINO_WAIT]
151 if CONF_SLEEP_TUNE
in data:
152 board_data[
"sleep_tune"] = data[CONF_SLEEP_TUNE]
154 board_data[
"autostart"] =
False
155 board_data[
"shutdown_on_exception"] =
True
156 board_data[
"close_loop_on_shutdown"] =
False
158 board = PymataExpress(**board_data)
160 await board.start_aio()
tuple[Literal[0, 1], int] get_pin_type(self, FirmataPinType pin)
bool async_setup(self, tries=0)
bool mark_pin_used(self, FirmataPinType pin)
None __init__(self, Mapping config)
PymataExpress get_board(Mapping data)