Platform example

I have an Arduino with 8 HTD21D temperature and humidity sensors, connected via TCA9548A I2C multiplexer. Code that works fine from CLI on my laptop:

import serial
import sys
import time
import struct
import array


ser = serial.Serial('/dev/ttyUSB0', 115200)  # open serial port

ser.timeout = 3

# Wait for port to get ready and send a data request
time.sleep(3)
ser.write(255)

# Read 8 temperature values
rawData = ser.read(4 * 8)
temperatures = array.array('f')
temperatures.frombytes(rawData)

# Read 8 humidity values
rawData = ser.read(4 * 8)
humidities = array.array('f')
humidities.frombytes(rawData)

# Print to console
for i in range(8):
    print('temperatures ', i, temperatures[i])
for i in range(8):
    print('humidities ', i, humidities[i])

ser.close()  

I have repeatedly read the section for developers, include https://developers.home-assistant.io/docs/en/creating_platform_example_sensor.html but cannot to make first step.

  • What do I need to write in my custom component ‘sensor.py’?
  • What do I need to write in the configuration.yaml to see 16 values stored in arrays?

Found the answer to my questions
My custom ‘sensor.py’

import sys
import time
import struct
import array

from homeassistant.const import (
    TEMP_CELSIUS, DEVICE_CLASS_HUMIDITY,
    DEVICE_CLASS_TEMPERATURE)
from homeassistant.helpers.entity import Entity


REQUIREMENTS = ['pyserial==3.4']

import serial
import logging

_LOGGER = logging.getLogger(__name__)


def setup_platform(hass, config, add_entities, discovery_info=None):
    
    """Set up the sensors."""
    add_entities([
        multiHTU21DSensor('Temperature1', 11.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 1),
        multiHTU21DSensor('Temperature2', 12.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 2),
        multiHTU21DSensor('Temperature3', 13.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 3),
        multiHTU21DSensor('Temperature4', 14.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 4),
        multiHTU21DSensor('Temperature5', 15.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 5),
        multiHTU21DSensor('Temperature6', 16.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 6),
        multiHTU21DSensor('Temperature7', 17.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 7),
        multiHTU21DSensor('Temperature8', 18.6, DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, 8),
        multiHTU21DSensor('Humidity1', 10, DEVICE_CLASS_HUMIDITY, '%', None, 1),
        multiHTU21DSensor('Humidity2', 20, DEVICE_CLASS_HUMIDITY, '%', None, 2),
        multiHTU21DSensor('Humidity3', 30, DEVICE_CLASS_HUMIDITY, '%', None, 3),
        multiHTU21DSensor('Humidity4', 40, DEVICE_CLASS_HUMIDITY, '%', None, 4),
        multiHTU21DSensor('Humidity5', 50, DEVICE_CLASS_HUMIDITY, '%', None, 5),
        multiHTU21DSensor('Humidity6', 60, DEVICE_CLASS_HUMIDITY, '%', None, 6),
        multiHTU21DSensor('Humidity7', 70, DEVICE_CLASS_HUMIDITY, '%', None, 7),
        multiHTU21DSensor('Humidity8', 80, DEVICE_CLASS_HUMIDITY, '%', None, 8),
    ])


class multiHTU21DSensor(Entity):
    """Representation of a sensor."""

    handler = None


    def __init__(self, name, state, device_class,
                 unit_of_measurement, battery, sensorNumber):
        """Initialize the sensor."""
        self._name = name
        self._state = state
        self._device_class = device_class
        self._unit_of_measurement = unit_of_measurement
        self._battery = battery
        self.sensorNumber = sensorNumber
 
        if self.sensorNumber == 1 and self._device_class == DEVICE_CLASS_TEMPERATURE:
            multiHTU21DSensor.handler = multiHTU21DSensorHandler()

    @property
    def should_poll(self):
        return True

    @property
    def device_class(self):
        """Return the device class of the sensor."""
        return self._device_class

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        if self._device_class == DEVICE_CLASS_TEMPERATURE:
            value = self.handler.get_temperature(self.sensorNumber)
        else:
            value = self.handler.get_humidity(self.sensorNumber)

        return value 


    @property
    def unit_of_measurement(self):
        """Return the unit this state is expressed in."""
        return self._unit_of_measurement

    def update(self):
        """Get the latest data and updates the states. Update only once for 16 sensors. """
        if self.sensorNumber == 1 and self._device_class == DEVICE_CLASS_TEMPERATURE:
            self.handler.update()


class multiHTU21DSensorHandler:
    """Implement HTU21D communication."""

    def __init__(self):
        # Operations with Arduino and values storage
        #self.temperatures = array.array('f')
        #self.humidities = array.array('f')
        self.temperatures = [10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]
        self.humidities = [11.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0]

        # Open port.
        self.ser = serial.Serial('/dev/ttyUSB0', 115200)  # open serial port
        self.ser.timeout = 3

        # Wait for port to get ready
        time.sleep(3)
        self.update()

    def get_temperature(self, index):
        """Return the temperature of the sensor with index."""
        return self.temperatures[index - 1]

    def get_humidity(self, index):
        """Return the humidity of the sensor with index."""
        return self.humidities[index - 1]

    def update(self):
        """Read raw data and calculate temperature and humidity."""

        # Send request.
        self.ser.reset_input_buffer()
        self.ser.write(1)

        # Read 8 float values of temperature
        rawData = self.ser.read(4 * 8)
        self.temperatures = array.array('f')
        self.temperatures.frombytes(rawData)
 
        # Read 8 float values of humidity
        rawData = self.ser.read(4 * 8)
        self.humidities = array.array('f')
        self.humidities.frombytes(rawData)

Into ‘configuration.yaml’

sensor:
  - platform: multiHTU21D