Smart Home and Building Automation
IoT where people live and work: smart home hubs and Home Assistant, Matter and Thread, building management systems and BACnet, energy management with solar panels, batteries and dynamic tariffs.
What a smart home is
A smart home is a home in which connected devices (lights, plugs, thermostats, sensors, meters, a battery) can be monitored and controlled remotely and act on each other through automations, such as "turn on the hall light when the front door opens after sunset". Three parts make it work:
- Devices: the sensors and actuators, each with a radio or a cable.
- A hub or controller that knows all devices, keeps their state and runs the automations. That can be a vendor's cloud service, a box from the vendor, or a small computer in the house.
- Interfaces for people: an app, a dashboard on the wall, voice assistants, physical switches that keep working.
Where the hub runs matters more than anything else. With a cloud-only system every light switch press makes a round trip to a data center; when the internet is down, or the vendor stops the service, the house stops being smart, and sometimes stops working. A local hub keeps working without the internet and keeps the data in the house. This is the local-first idea applied to a home.
Lotte Kortenhoeve's home in Utrecht is a good example. She has solar panels, a dynamic contract with Kestrel and a smart meter with a P1 port. An ESP32 board on that port reads the meter every second (see the P1 page) and publishes to a local MQTT broker on a Raspberry Pi 5, which also runs Home Assistant. Home Assistant shows her use, controls a home battery and receives Kestrel's hourly prices.
Kestrel receives nothing from this setup. Her second-by-second data stays in the house, except for the live power that her Kestrel Home pilot dongle sends with her consent (see Provisioning and Over-the-Air Updates).
Hubs and Home Assistant
Home Assistant is open-source home automation software that runs on a computer in the house, often a Raspberry Pi or a small PC, connects to devices of many brands through integrations, keeps their history and runs automations locally. It has been owned since April 2024 by the Open Home Foundation, a non-profit that also looks after ESPHome. A new version appears on the first Wednesday of every month, numbered by year and month (2026.9 was the September 2026 release), so updates are routine and frequent.
Things Lotte uses it for:
- The DSMR integration, which reads Dutch, Belgian, Luxembourg and Swedish smart meters, and an MQTT integration that subscribes to her own broker.
- The energy dashboard, which combines the grid meter, solar production, the battery, gas and individual devices into one daily, weekly and monthly overview.
- Automations for the battery, written in YAML or with the visual editor.
A Home Assistant automation that tells the battery to stop feeding the house while the electricity is cheap (illustrative: entity names are Lotte's own, and option names change between releases, so check the current documentation):
- alias: "Battery: hold charge while power is cheap"
triggers:
- trigger: numeric_state
entity_id: sensor.kestrel_price_now
below: 0.25
conditions:
- condition: state
entity_id: input_boolean.battery_manual_override
state: "off"
actions:
- action: select.select_option
target:
entity_id: select.home_battery_mode
data:
option: "hold"
Note the condition: when Lotte switches the manual override on, the automation leaves the battery alone. Every automation that moves energy or locks doors should have such a switch, and the household should know where it is.
ESPHome
ESPHome is an open-source system for
building firmware for ESP32 and similar boards from a YAML
configuration file instead of code: you describe the pins, buses and
sensors, and ESPHome generates, compiles and flashes the firmware,
then updates it over the air. It has ready-made components for
hundreds of sensors, including a dsmr component for the
P1 port. After a first version in MicroPython (see
Firmware and Embedded Programming), Lotte moved her P1 reader to ESPHome. The core of her
configuration (illustrative; the secrets file keeps passwords out of
the YAML, so this block is not checked):
esphome:
name: p1-reader
esp32:
board: esp32dev
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
mqtt:
broker: 192.168.1.20
username: p1-reader
password: !secret mqtt_password
uart:
rx_pin:
number: GPIO16
inverted: true # the P1 data line is logically inverted
baud_rate: 115200 # DSMR 4 and 5
rx_buffer_size: 1700 # a whole telegram must fit
dsmr:
max_telegram_length: 1700
sensor:
- platform: dsmr
energy_delivered_tariff1:
name: "Energy delivered tariff 1"
energy_delivered_tariff2:
name: "Energy delivered tariff 2"
power_delivered:
name: "Power delivered"
Three lines carry the hard-won knowledge of the P1 page: the data
line is inverted, the speed is 115200 baud, and the receive buffer
must hold a complete telegram. The wiring rules (a pull-up to 3.3 V,
never 5 V on an ESP32 pin) are the same as for any other reader. One
thing changes with the move: ESPHome publishes each sensor under its
own topic, such as
p1-reader/sensor/power_delivered/state, instead of the
home/p1/power of the MicroPython version. A sensor's
state_topic option can keep the old topic; otherwise
every subscriber has to follow the new one.
Matter and Thread
For years every smart home brand had its own app, hub and cloud, and devices of different brands did not work together. Matter is an application-layer standard of the Connectivity Standards Alliance that defines how smart home devices describe themselves and are controlled, so that a Matter light works with any Matter controller. Key properties:
- It runs over IP networks: Wi-Fi, Ethernet and Thread, a low-power mesh network based on IPv6. Bluetooth Low Energy is used only to set a device up.
- It works locally. Control goes directly from the controller to the device in the house; no cloud is needed.
- Onboarding is standardized: scan the code on the device, and the controller adds it to the home network.
- Every device carries a device attestation certificate, which proves it is a certified product of a known manufacturer, the same per-device identity idea as on Provisioning and Over-the-Air Updates.
- One device can be used by several controllers at the same time, for example a phone platform and Home Assistant.
As of October 2026 the current version is Matter 1.6 (June 2026), which added commissioning over NFC; Matter 1.5 (November 2025) added cameras, closures, soil sensors, energy tariff information and bidirectional EV charging, which brings energy management inside the standard.
Zigbee, an older mesh standard on the same IEEE 802.15.4 radio as Thread, is still in many homes; bridges translate it for Home Assistant or for Matter controllers. The radios themselves are compared on Wireless Basics.
Building automation
Offices, hospitals, schools and data centers have the same needs as a smart home at a larger scale, with stricter requirements. A building management system (BMS, also called a building automation system) is the control system that monitors and controls a building's technical installations, such as heating, ventilation and air conditioning (HVAC), lighting, sun blinds, access control and energy meters, from central workstations, with controllers in plant rooms and on every floor. It is operational technology: when it fails, people are cold, rooms overheat, or the server room's cooling stops.
BACnet
BACnet (Building Automation and Control Networks) is the main open protocol of building automation: it lets controllers, sensors and workstations of different manufacturers exchange data and commands. It is published as ANSI/ASHRAE Standard 135 (latest edition 135-2024) and as ISO 16484-5 (latest edition 2026). Its main transports:
- BACnet/IP: over UDP, port 47808. The industrial protocols page introduces it among other OT protocols.
- BACnet MS/TP: over an RS-485 serial line, for the controllers on each floor.
- BACnet/SC (Secure Connect): over WebSockets with TLS, the answer to the fact that classic BACnet/IP and MS/TP traffic is, in practice, neither encrypted nor authenticated.
Everything in a BACnet device is an object with
properties: an analog-input object for a temperature sensor
has a Present_Value property with the current reading,
a binary-output object switches a pump. Each object is
named by a 32-bit object identifier: 10 bits for the object type and
22 bits for the instance number. Decoding one is an exercise in
bit shifts
and masks:
OBJECT_TYPES = {0: "analog-input", 1: "analog-output", 2: "analog-value",
3: "binary-input", 4: "binary-output", 5: "binary-value",
8: "device"}
def encode(object_type, instance):
"""BACnet object identifier: 10 bits of type, 22 bits of instance."""
return object_type << 22 | instance
def decode(identifier):
object_type = identifier >> 22
instance = identifier & 0x3FFFFF # the lowest 22 bits
return OBJECT_TYPES.get(object_type, f"type {object_type}"), instance
for identifier in (0x00000003, 0x00C00010, 0x0080000C, 0x020003E9):
name, instance = decode(identifier)
print(f"0x{identifier:08X} {name} {instance}")
print(f"device 1001 encodes as 0x{encode(8, 1001):08X}")
print(f"BACnet/IP port 47808 = 0x{47808:X}")
0x00000003 analog-input 3 0x00C00010 binary-input 16 0x0080000C analog-value 12 0x020003E9 device 1001 device 1001 encodes as 0x020003E9 BACnet/IP port 47808 = 0xBAC0
The port number is not an accident: 47808 is
0xBAC0. The other big open standard in Europe is
KNX, common for lighting, blinds and room control
in both homes and offices; older plant often speaks
Modbus, and
gateways translate between them.
Home energy management
A home energy management system (HEMS) is software, in a hub, an inverter or a cloud service, that decides when the large energy users and producers in a home run: when the battery charges or discharges, when the heat pump heats the water, when the car charges, and whether solar power is used, stored or fed into the grid. It works from prices, weather and consumption forecasts, the household's preferences and any limits the grid sets. The term is different from the energy management system of a grid control center, which runs a whole power system.
Several changes make a HEMS more useful in the Netherlands:
- Net metering ends on 1 January 2027. Until then, solar power fed into the grid is subtracted from power taken from it on the annual bill, which makes the grid a free battery. After that, feeding in earns less than buying costs: until 2030 the compensation must be at least 50% of the supply price before taxes. Using your own solar power yourself becomes worth more.
- Dynamic contracts make the price of each hour different, so moving use in time saves money directly.
- Grid congestion means the local grid cannot always take more (see grid congestion). Homes that shift use away from the busiest hours help; homes whose systems all react to the same price signal at the same minute can create a new peak.
Dynamic tariffs and a battery schedule
A dynamic energy contract is an energy contract in which the price per kWh follows the wholesale day-ahead market: it changes per hour or per quarter hour, and the prices for tomorrow are known today. The customer pays that market price plus the supplier's fixed markup, energy tax and VAT. Kestrel prices its dynamic contract per hour; the market itself has traded per quarter hour since 1 October 2025.
Lotte's contract, CT-20004, has been dynamic since 1 July 2026. Her Home Assistant takes tomorrow's prices and plans the battery: charge in the cheapest hours of the day, discharge in the most expensive hours of the evening, never more than the house uses at that time (feeding battery power into the grid is a different calculation). The prices, the use and the battery are invented; the method is the one most HEMS start from:
from decimal import Decimal as D
# Invented all-in prices (EUR/kWh incl. taxes) for one day, hour 0 = 00:00-01:00
PRICES = [D(p) for p in """
0.262 0.255 0.249 0.246 0.248 0.257 0.281 0.312 0.305 0.276 0.248 0.221
0.203 0.192 0.196 0.226 0.259 0.318 0.364 0.382 0.351 0.312 0.285 0.268
""".split()]
# Expected household use in the evening (kWh per hour), from her own history
EVENING_USE = {17: D("1.2"), 18: D("1.6"), 19: D("1.4"), 20: D("1.1"),
21: D("0.9"), 22: D("0.7"), 23: D("0.5")}
CAPACITY = D("5.0") # kWh the battery stores when full (assumption)
MAX_RATE = D("2.5") # kW, charge or discharge (assumption)
EFFICIENCY = D("0.90") # round trip: 90% of what goes in comes back out
# Charge in the cheapest hours before 17:00, until the battery is full
charge, stored = {}, D(0)
for hour in sorted(range(17), key=lambda h: PRICES[h]):
if stored >= CAPACITY:
break
charge[hour] = min(MAX_RATE, CAPACITY - stored)
stored += charge[hour]
# Discharge in the most expensive evening hours, never more than the house uses
available, discharge = stored * EFFICIENCY, {}
for hour in sorted(EVENING_USE, key=lambda h: PRICES[h], reverse=True):
if available == 0:
break
discharge[hour] = min(MAX_RATE, EVENING_USE[hour], available)
available -= discharge[hour]
cost = sum(kwh * PRICES[h] for h, kwh in charge.items())
avoided = sum(kwh * PRICES[h] for h, kwh in discharge.items())
for hour in sorted(charge | discharge):
if hour in charge:
action = f"charge {charge[hour]:.2f} kWh"
else:
action = f"discharge {discharge[hour]:.2f} kWh"
print(f"{hour:02}:00 EUR {PRICES[hour]}/kWh {action}")
print(f"bought for the battery: EUR {cost.quantize(D('0.01'))}")
print(f"grid use avoided: EUR {avoided.quantize(D('0.01'))}")
print(f"saving on this day: EUR {(avoided - cost).quantize(D('0.01'))}")
13:00 EUR 0.192/kWh charge 2.50 kWh 14:00 EUR 0.196/kWh charge 2.50 kWh 17:00 EUR 0.318/kWh discharge 0.40 kWh 18:00 EUR 0.364/kWh discharge 1.60 kWh 19:00 EUR 0.382/kWh discharge 1.40 kWh 20:00 EUR 0.351/kWh discharge 1.10 kWh bought for the battery: EUR 0.97 grid use avoided: EUR 1.63 saving on this day: EUR 0.66
What the example shows, and what it leaves out:
- Efficiency costs money. 5 kWh go in, 4.5 kWh come out. The price difference between the charge and discharge hours must be larger than that loss, or cycling the battery loses money.
- The cheapest hours are at midday, when solar power floods the market. On a sunny day Lotte's battery charges from her own panels at that time, which is even cheaper; the example buys from the grid to keep the calculation simple.
- Decimal, not float, because these are amounts of money (see floating-point numbers).
- Real systems add more: forecasts that are wrong, battery wear per cycle, the inverter's own consumption, and grid limits. An optimizer replaces the two sorted lists, but the inputs and the check "is this worth a cycle?" stay the same.
Privacy, safety and reliability
A smart home collects intimate data and controls physical things. Both deserve care:
- Energy data is personal data. A second-by-second power curve shows when someone is home, asleep or away. Dutch rules limit what grid operators and suppliers may collect (see smart-meter data); in her own house, keeping the data local is Lotte's best protection.
- Separate the devices. Put smart home devices on their own network, such as a guest network or a separate VLAN, so a cheap plug with old firmware cannot reach the laptop with the tax return. See IoT Security.
- Keep a manual way. Wall switches must still switch the light when the hub is down; the battery needs an override; the front door needs a key.
- Plan for the vendor. Devices that depend on a vendor's cloud stop working when the vendor stops the service. Prefer devices that work locally, through Matter, Zigbee or ESPHome, and keep the hub updated.