After several years of testing different devices and software for the smart home, I found the definitive solution: Home Assistant. It is an open-source home automation platform that allows you to control and monitor various devices and services within your home. It serves as a centralized hub that connects and integrates different smart devices, systems, and services, enabling you to automate and manage them through a single interface.
The main goal of Home Assistant is to provide a unified platform for home automation, regardless of the brand or protocol used by the devices. It supports a wide range of devices, including smart lights, thermostats, sensors, cameras, media players, and more. By integrating these devices into Home Assistant, you can create complex automation routines, control them remotely, and gather data for analysis and visualization.
Virtualization
As described in previous articles I’m using the Docker environment to host all the local services and so I’m going to install Home Assistant within the Docker Engine. As for all the Docker containers, the installation procedure is very easy. Just run the following commands with the correction of your time zone:
docker run -d \
--name homeassistant \
--privileged \
--restart=unless-stopped \
-e TZ=MY_TIME_ZONE \
-v /PATH_TO_YOUR_CONFIG:/config \
--network=host \
ghcr.io/home-assistant/home-assistant:stable
Then you can log in to Home Assistant via the web interface: http://<host>:8123
.
The majority of the Home Assistant configuration is made through the configuration.yaml
file, so I configured VSCode to login into my server through SSH. It requires the Remote – SSH Extension and you can log in as root@<host>
.

So I can start to configure all the devices. I added the official integration to connect all the smart home services like Sonoff, Meross, Tado, etc. It was very easy to add all the devices but I have to understand how to organize all the dashboards for an efficient visualization.

Community Store Integration
Before completing the initial configuration I understood that I need more than the official integration so I installed the HACS repository. It is the Home Assistant Community Store that allows you to install extra features. For instance, I’m currently using:
- Alexa Media Player
- Kiosk Mode
- Meross LAN
- Room Card
- Apex charts
- Plotly
- Auto-entities
Custom thermostat
And finally, I can start customizing my smart home. The first virtual device that I want to create is a thermostat. I know, I have a Tado a there are a lot of possible ways to create a thermostat, however, I want to use my custom-made temperature sensors. They have a web interface that I can use to read the temperature inside Home Assistant.
I can use the rest
sensor platform. It is consuming a given endpoint that is exposed by a RESTful API of a device, an application, or a web service. The sensor has support for GET and POST requests. Inside the configuration file I should add:
- platform: rest
resource: http://192.168.1.114/temperature
name: Temperature Cucina
unit_of_measurement: "°C"
unique_id: temperature_cucina


The previous code will give me a temperature sensor inside Home Assistant that I can link as the thermostat target sensor. The following code creates a custom thermostat that uses a Sonoff switch as an actuator driven by the temperature variation of the aforementioned sensor.
climate:
- platform: generic_thermostat
name: Salone
unique_id: salone_custom_thermostat
heater: switch.sonoff_1000c57470
target_sensor: sensor.temperature_cucina
min_temp: 10
max_temp: 25
target_temp: 20
hot_tolerance: 0.5
cold_tolerance: 2
Tado integration
The next step involves the customization of the Tado thermostat. Essentially, I created a new entity that controls the Tado’s actuator based on a different temperature sensor. Firstly it requires the creation of a virtual switch to control the Tado as follows:
switch:
- platform: template
switches:
blind:
friendly_name: "Termosifoni Camere"
unique_id: termosifoni_camere
turn_on:
- service: tado.set_climate_timer
target:
entity_id: climate.camera_di_mamma
data:
temperature: "{{ state_attr('climate.camere','temperature')|float }}"
turn_off:
- service: climate.turn_off
entity_id: climate.camera_di_mamma
Then the aforementioned switch will be controlled by a new thermostat based on the desired temperature sensor.
With a similar procedure, I added another typology of entities, the dual thermostat
. It allows me to connect both the heating system (the aforementioned switch) and the cooling system. The cooling unit is an air conditioner controlled by a BroadLink RM Mini that emulates its IR controller.
climate:
- platform: dual_smart_thermostat
name: Camera ale
unique_id: thermostat_ale
heater: switch.termosifonicamere
cooler: switch.condizionatore_ale
target_sensor: sensor.temperature_camera_ale
min_temp: 10
max_temp: 25
target_temp: 20
hot_tolerance: 0.5
cold_tolerance: 2
Furthermore, it could be easily integrated with the HomeKit Apple ecosystems through the HomeKit integration.


MQTT
A lot of smart home devices use MQTT (Message Queuing Telemetry Transport). It is a lightweight messaging protocol designed for efficient communication between devices in constrained networks, such as those with low bandwidth or unreliable connections. An MQTT broker acts as a central hub or intermediary that facilitates the exchange of messages between publishers and subscribers in an MQTT-based system. The MQTT broker works:
- Publishers: devices or applications that generate and send messages, to the broker, containing data or information that needs to be distributed to interested parties.
- Subscribers: devices or applications that are interested in receiving specific messages. T
- Topics: act as message channels or categories within the MQTT broker. Publishers send messages to specific topics, and subscribers can choose to receive messages from one or more topics by subscribing to them.
- Message Distribution: When a publisher sends a message to a topic on the MQTT broker, the broker receives the message and distributes it to all the subscribers that have subscribed to that particular topic.
- Quality of Service (QoS): MQTT supports different levels of QoS to ensure reliable message delivery. QoS levels include:
- QoS 0 (At most once): The message is delivered once without any confirmation or guarantee of receipt.
- QoS 1 (At least once): The message is delivered at least once, and the receiver sends an acknowledgment back to the publisher for confirmation.
- QoS 2 (Exactly once): The message is delivered exactly once by using a two-step handshake process to ensure reliable and ordered delivery.
- Broker Persistence: MQTT brokers can be designed to persist messages even when subscribers are not currently connected.
- Security and Authentication: MQTT brokers often support authentication and encryption mechanisms to ensure secure communication between devices. This may include username/password authentication, Transport Layer Security (TLS), or other security measures.
Mosquitto broker
So I needed an MQTT broker and I decided to install the Mosquitto broker inside the Docker container.

As for the other Docker installations, we can start from the docker-compose.yaml
file:
mosquitto:
image: eclipse-mosquitto
container_name: mosquitto
volumes:
- /opt/mosquitto:/mosquitto
- /opt/mosquitto/data:/mosquitto/data
- /opt/mosquitto/log:/mosquitto/log
ports:
- 1883:1883
- 9001:9001
With this fail stored in the /mosquitto
folder we need to add another configuration file: /mosquitto/config/mosquitto.conf
as:
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
listener 1883
## Authentication ##
allow_anonymous true
And finally, build up the container with the composer:
docker-compose up -d
Then we need to add the other user who can use the Mosquitto broker. Login into the container and run into its shell the following command:
mosquitto_passwd -c /mosquitto/config/password.txt hass
After prompting the password you can switch back to the configuration file and add the last line to enable the created user password:
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
listener 1883
## Authentication ##
allow_anonymous true
password_file /mosquitto/config/password.txt
The last step is to add the user-password relation in all the MQTT devices starting with Home Assistant. For more information see: Configuring the Mosquitto MQTT Docker container for use with Home Assistant.
Tasmota
Tasmota is an open-source firmware that can be installed on various Internet of Things (IoT) devices, particularly those that are based on the ESP8266 and ESP32 microcontrollers. It allows you to replace the original firmware on these devices, providing greater control and customization options.
The Tasmota firmware is designed to provide a flexible and feature-rich environment for IoT devices. It offers support for a wide range of protocols and integrations, including Wi-Fi, MQTT (Message Queuing Telemetry Transport), HTTP, and more. By flashing Tasmota onto compatible devices, you can transform them into smart devices that can be controlled and monitored remotely. For instance, I flashed several Sonoff obtaining custom and advanced features.

To enable MQTT, after setting username and password in the GUI, remember also to set:
SetOption19 0
Energy monitor
Another advanced example of Tasmota was created with a custom circuit. By using a CT (Current Transformer) Clamp it is possible to measure the current and power consumption of devices. It is a device used to measure the electric current flowing through a conductor without the need to physically disconnect the circuit.
The basic principle behind a CT clamp is electromagnetic induction. It consists of a ferromagnetic core (typically in the shape of a split ring or a jaw) and a coil of wire wrapped around the core. The conductor carrying the current is passed through the core or placed inside the clamp’s jaw. When an electric current flows through the conductor, it creates a magnetic field around it according to Ampere’s law. The CT clamp takes advantage of this magnetic field. The magnetic field induced by the current in the conductor interacts with the ferromagnetic core of the clamp, causing a proportional magnetic field in the core.
Home power consumption
With the Tasmota firmware, we can read the clamp signal. The following is an example of the application of the SCT-013-xxx clamp to measure a three-phase current. Each clamp shows an output of 1V that linearly vary with respect to the current.
Do not operate with line cable, 230V could be very dangerous. Seek help from a professional electrician.


It is really easy to implement in the Tasmota firmware. I flashed a Wemos D1 for each current phase connecting three clamps in total. Then each clamp read a cable of the three-phase power source for electricity inside the house.
Linear relation mapping
For each device, inside the Tasmota configuration set the ADC CT Power device and with the console, you can refine the sensitivity.
<Sensor>, <param1>, <param2>, <param3>, <param4>
The AdcParam
command requires five parameters:
7
, is used to mark the CT POWER senso asAdcParam 7
<param1>
, set as 0 marking a non-invasive current sensor<param2>
, use to select the typology of CT Clamp with respect to the maximal ampere, here I used a 20A clamp: the STC-013-020. It is the scaling factor to convert the voltage output in the 0-1023 range of the analog converter.<param3>
, the maximum voltage/1000. Here, it is 230 V and so 0.230.<param4>
, the minimum current threshold
AdcParam 7,0,2146,0.230,0.060
You could use Tasmota to calibrate the sensor however I preferred some post-processing inside Home Assistant. The idea was to use two fixed and known loads, preferably a resistive one as a filament lamp, to mark two points in the linear relation. I also used a professional Amprobe to double-check the power consumption. For each load, you need to mark the output values from the Tasmota s
and the real load w
.
- s1, w1
- s2, w2
Then it is possibile to map each value of the signal to obtain the current wattage as:
w=w_1+(w_2-w_1){s-s_1\over s_3-s_1}
Then we need a Rieman integration helpers to integrate watt in each time steps into Wh and then an Utility Meter to split the integral into each day/hours values.
Utility meter code block
utility_meter:
daily_energy_server_room:
source: sensor.server_room_power_integration_kwh
name: Daily Energy Server Room
cycle: daily
hourly_update_energy_server_room:
source: sensor.server_room_power_integration_wh
name: Hourly Update Energy Server Room
cycle: hourly
hourly_armadietto_energy:
source: sensor.integration_power_armadietto_fra
name: Energy Armadietto Fra
cycle: hourly
monthly_energy_server_room:
source: sensor.server_room_power_integration_kwh
name: Monthly Energy Server Room
cycle: monthly
daily_energy_home:
source: sensor.energy_consumption
name: Daily Energy Home
cycle: daily
hourly_energy_home:
source: sensor.energy_consumption
name: Hourly Energy Home
cycle: hourly
monthly_energy_home:
source: sensor.energy_consumption
name: Monthly Energy Home
cycle: monthly
hourly_energy_l1:
source: sensor.l1_power_integration_kwh
name: Hourly Energy l1
cycle: hourly
hourly_energy_l2:
source: sensor.l2_power_integration_kwh
name: Hourly Energy l2
cycle: hourly
hourly_energy_l3_2:
source: sensor.l3_power_integration_kwh
name: Hourly Energy l32
cycle: hourly

Sensor data mapping
- sensor:
- name: "L1 corrected power"
state: >
{% set s1=64.0 %}
{% set s2=600.0 %}
{% set w1=40.0 %}
{% set w2=1100.0 %}
{{(w1+ (w2-w1)*(states('sensor.l1_analog_ctenergy_power') |float(1) -s1)/(s2-s1)) | round(0)}}
unit_of_measurement: W
- sensor:
- name: "L2 corrected power"
state: >
{% set s1=20.0 %}
{% set s2=550.0 %}
{% set w1=40.0 %}
{% set w2=1000.0 %}
{{(w1+ (w2-w1)*(states('sensor.l2_analog_ctenergy_power') |float(1) -s1)/(s2-s1)) | round(0)}}
unit_of_measurement: W
- sensor:
- name: "L3 corrected power"
state: >
{% set s1=120.0 %}
{% set s2=950.0 %}
{% set w1=50.0 %}
{% set w2=890.0 %}
{{(w1+ (w2-w1)*(states('sensor.l3_analog_ctenergy_power') |float(1) -s1)/(s2-s1)) | round(0)}}
unit_of_measurement: W

Three-phase power computation
- sensor:
- name: "Home Power"
state: "{{(0.001* (states('sensor.l1_corrected_power') |float(0) + states('sensor.l2_corrected_power') |float(0)+states('sensor.l3_corrected_power') |float(0) ) )|round(3)}}"
unit_of_measurement: kW
The actual power consumption needs some refinement but it is relatively precise with less than 5% deviation from the energy-supplier one.

Media player
With the HACS Alexa integration, you can control each Amazon player device. For instance, I created a custom card showing only active devices:


Yaml card configuration
type: vertical-stack
cards:
- type: entities
entities: []
title: Media
- type: custom:auto-entities
show-empty: true
card:
type: glance
filter:
include:
- domain: media_player
exclude:
- state: 'off'
- state: standby
- name: This*
- type: conditional
conditions:
- entity: media_player.echo_show_di_alessandro
state: playing
card:
type: media-control
entity: media_player.echo_show_di_alessandro
- type: conditional
conditions:
- entity: media_player.tv_sala_hobby
state: playing
card:
type: media-control
entity: media_player.tv_sala_hobby
- type: conditional
conditions:
- entity: media_player.lg_webos_smart_tv
state: 'on'
card:
type: media-control
entity: media_player.lg_webos_smart_tv
- type: conditional
conditions:
- entity: media_player.echo_dot_studio
state: playing
card:
type: media-control
entity: media_player.echo_dot_studio
- type: conditional
conditions:
- entity: media_player.echo_dot_bagno_ragazzi
state: playing
card:
type: media-control
entity: media_player.echo_dot_bagno_ragazzi
- type: conditional
conditions:
- entity: media_player.sony_kd_75xh8096
state: 'on'
card:
type: media-control
entity: media_player.sony_kd_75xh8096
- type: conditional
conditions:
- entity: media_player.alessandro_s_2nd_fire_tv_stick
state: 'on'
card:
type: media-control
entity: media_player.alessandro_s_2nd_fire_tv_stick
- type: conditional
conditions:
- entity: media_player.fire_tv_ale
state: playing
card:
type: media-control
entity: media_player.fire_tv_ale
- type: conditional
conditions:
- entity: media_player.echo_dot_cucina
state: playing
card:
type: media-control
entity: media_player.echo_dot_cucina
- type: conditional
conditions:
- entity: media_player.echo_dot_camera_di_francesco
state: playing
card:
type: media-control
entity: media_player.echo_dot_camera_di_francesco
Custom dashboard
I created several Lovelace cards to resume information inside the main dashboards. For instance, the main dashboard shows the temperature of different rooms, people’s location, actual power for the three phases as well as the average energy consumption in the previous 24 hours and the devices currently turned on.

Devices on

type: custom:auto-entities
show-empty: true
card:
type: glance
title: Devices on
filter:
include:
- state: 'on'
exclude:
- name: '*Remote*'
- name: '*dnd'
- name: Tado*
- name: '*Focus'
Energy consumption
type: vertical-stack
cards:
- type: entities
title: Average Hourly Consumption
entities: []
- type: custom:apexcharts-card
stacked: true
graph_span: 1d
apex_config:
legend:
position: top
fontSize: 14px
itemMargin:
horizontal: 10
vertical: 5
all_series_config:
type: column
unit: kWh
float_precision: 3
opacity: 0.7
show:
legend_value: false
group_by:
func: max
duration: 1h
fill: zero
series:
- entity: sensor.hourly_energy_l1
name: L1
- entity: sensor.hourly_energy_l2
name: L2
- entity: sensor.hourly_energy_l32
name: L3
- type: entities
title: Average Daily Consumption
entities: []
- type: custom:apexcharts-card
stacked: true
graph_span: 30d
apex_config:
legend:
position: top
fontSize: 14px
itemMargin:
horizontal: 10
vertical: 5
all_series_config:
type: column
unit: kWh
float_precision: 2
opacity: 0.7
show:
legend_value: false
group_by:
func: max
duration: 1d
fill: zero
series:
- entity: sensor.daily_energy_home
name: server room
Three-phase energy monitor

type: vertical-stack
cards:
- type: gauge
entity: sensor.home_power
needle: true
min: 0
max: 3.5
severity:
green: 0
yellow: 0.5
red: 3
unit: kW
name: Power
- type: horizontal-stack
cards:
- type: gauge
entity: sensor.l1_corrected_power
unit: W
name: L1
min: 0
max: 3000
needle: false
severity:
green: 0
yellow: 500
red: 1000
- type: gauge
entity: sensor.l2_corrected_power
unit: W
name: L2
min: 0
max: 3000
needle: false
severity:
green: 0
yellow: 500
red: 1000
- type: gauge
entity: sensor.l3_corrected_power
unit: W
name: L3
min: 0
max: 3000
needle: false
severity:
green: 0
yellow: 500
red: 1000
A special dashboard is dedicated to the thermal system where I can monitor temperature, boiler, solar panel, radiator, and pump status and drive the heating or cooling systems. This dashboard and how I created it will be described in a further article.

I also created a dashboard for single-room resumes:

Energy dashboard
In addition, I started using the Home Assistant Energy Dashboard to include all the information about electricity and gas consumption. Furthermore, besides the Solar segment should be related to the electrical energy produced by solar panels, I decided to use it to insert information about the thermal energy produced by the solar panel.

I made other advanced configurations for thermal systems control and some custom cards but I’ll talk about that in further articles.


