Sitemap
Jonathan

Jonathan

Lead developer of lcdwizard.com

A wall panel for Home Assistant, over MQTT, without writing the code

What a broker is, how to set one up, and an ESP32 touchscreen that reads the house and switches the porch light.

9 min readOct 29, 2026

--

The finished panel in Preview, reading the house.

MQTT is how a lot of home kit talks: sensors, smart plugs, Zigbee2MQTT, Tasmota, ESPHome, and Home Assistant itself. A little touchscreen on the wall that joins in is one of the nicest things you can add to a smart home, and one of the fiddliest to build by hand.

This walk-through builds one in LCD Wizard, a browser-based designer for ESP32 display boards. The board is an LCDWIKI ES3C35P (3.5 inches, 320 x 480), but nothing here is special to it. The panel reads six values from the house, switches the porch light, and turns up in Home Assistant as a device of its own.

Every step was carried out in the designer to take its picture, against a real capture of a pretend house: a small program that publishes lights, heating, solar and a doorbell to a broker, with Home Assistant watching it.

The same set-up has run on a real board, a Waveshare ESP32-P4 4.3, against a real MQTT broker: it turned up in Home Assistant by itself and was controlled from there both ways. The ES3C35P build shown here has been compiled, not yet run.

First, what a broker is

A broker is a post office for small messages. Nothing on MQTT talks to anything else directly. Every device connects to the broker, and the broker passes messages on.

  • A message goes to a topic, a name with slashes in it such as house/outside/temperature. Saying something on a topic is publishing.
  • Anything that wants to hear a topic subscribes to it. house/light/+/state means every room's light, and house/# means everything under house.
  • A message can be retained. The broker keeps the last one and hands it to anyone who subscribes later, which is how a panel switched on in the morning knows straight away that the porch light is off.

Home Assistant is not the broker. It’s one more client, the same as your sensors and the panel. So the panel points at the broker, never at Home Assistant’s web page. If Home Assistant lives at http://192.168.1.20:8123 and the broker runs on the same machine, the panel's broker is 192.168.1.20, port 1883. Port 8123 is Home Assistant's website, and the board doesn't speak to it. This one catches a lot of people.

Setting up the broker

Home Assistant OS

  1. Go to Settings > Add-ons > Add-on store, find Mosquitto broker, install it and start it. It runs on the same machine as Home Assistant, on port 1883.
  2. Settings > Devices & services will offer the MQTT integration. Press Configure and accept.
  3. Make a login for the panel. The add-on lets in Home Assistant’s own users, so add a user called something like panel with its own password. Give each device its own login, not yours.

Home Assistant in Docker

Home Assistant Container has no add-ons, so the broker is a container of its own beside it, from the eclipse-mosquitto image, with a config that listens on the network and asks for a password:

listener 1883
allow_anonymous false
password_file /mosquitto/config/passwd
persistence true
persistence_location /mosquitto/data/

Make the password file with mosquitto_passwd -c /mosquitto/config/passwd panel inside the container. Leave out -c for every user after the first, or it starts the file again. Add one for Home Assistant too, restart the container, publish port 1883, and add the MQTT integration in Home Assistant by hand.

One thing worth knowing early: Home Assistant’s MQTT integration connects to one broker. If you already have another one (a Zigbee2MQTT box with its own, say), use that one for everything or join the two with a bridge. There’s more on that near the end.

Pointing the panel at the broker

Start a new Arduino project in the designer, pick the board, and open the Data tab’s MQTT window. It has five tabs: Broker, Topics, Publishing, Home Assistant and Import. On Broker, tick Connect, type the broker’s address, leave the port at 1883, and type the panel’s login.

Press enter or click to view image in full size
Connect on, the broker’s address, and the panel’s own login.

Use the address as numbers. homeassistant.local works on your computer but not on the board, which doesn't look up .local names. Most routers can be told to keep the Home Assistant machine on the same address.

Grabbing the topics instead of typing them

The designer runs in a browser and can’t see your broker, which sits on your own network behind a password. Typing every topic in by hand is tedious and easy to get wrong, so you grab them instead.

MQTT Wizard is a free desktop app. It connects to your broker with a login you give it, listens for a few seconds, and saves what it heard to a file: every topic, the last thing said on it, whether it was retained, and every device that announced itself to Home Assistant. Your password isn’t written to the file.

Load that file on the Import tab. Topics show as a tree on the left, and the Home Assistant devices it heard sit on the right, each entity with the topics it’s read from and the ones it takes commands on.

Press enter or click to view image in full size
The grab loaded: 65 topics and the pretend house’s 24 entities.

For this panel I ticked the porch light (listen to its state, publish to its command topic), the outside temperature, the solar power, the battery, and the living room’s current temperature.

Press enter or click to view image in full size
The porch light’s state ticked to listen to, and its command to publish.

Press Import with “Make variables too” and “Make publish actions for commands” ticked. Each topic gets a variable that holds what it last said, because widgets bind to variables rather than to topics. Each command becomes a ready-made publish, here “Porch light ON” and “Porch light OFF”, waiting to be put on a button.

Press enter or click to view image in full size
Five topics, five variables and two ready-made publishes, in one go.

A design listens to up to 24 topics per screen. If you tick more than fits, Import tells you how many to untick and changes nothing. The whole import is one change, so a single Undo takes it all back.

Reading one value out of a JSON message

Not every device sends one value per topic. Zigbee2MQTT puts a whole sensor in one message, like {"temperature":21.4,"humidity":48,"battery":92} on zigbee2mqtt/hall_sensor. On the Topics tab, add a topic, set its type to Number and its path into the JSON to temperature. Deeper values use dots and brackets, such as update.state or readings[0].value. Paste a sample message and the row shows what it reads.

Press enter or click to view image in full size
One topic, one key out of it: reads 21.4.

The panel itself

A dark screen, a title, four labels for outside, living room, hall and solar, a bar for the battery, a switch for the porch light with On and Off buttons under it, and a quiet mode switch. Each label is bound to its variable with a prefix, a format and a unit, so “Outside” becomes “Outside 12.3 °C” on the board.

Get Jonathan’s stories in your inbox

Join Medium for free to get updates from this writer.

The porch light switch follows the light one way only. The house reports the light’s state on one topic and takes commands on another, which is how a well-behaved device works: you ask on .../set, and the state changes once the light has actually done it. The buttons do the asking. Give On a Clicked event with "Publish to MQTT", pick "Porch light ON" from the ready-made list, and the topic and payload fill themselves in.

Clicked, Publish to MQTT, and the ready-made “Porch light ON”.

The board also needs a way onto Wi-Fi, and the designer keeps warning until it has one. A second screen with a WiFi Setup widget and a small Wi-Fi button on the main screen sorts that out. The board remembers the network and rejoins it each time it starts.

The finished Home screen.

The panel as a device in Home Assistant

So far the panel listens to the house. This part goes the other way: values that belong to the panel, visible and settable in Home Assistant, with no YAML. The panel announces them by MQTT discovery, the same way Zigbee2MQTT and ESPHome devices announce themselves.

On the Home Assistant tab, tick Announce, give the device a name, and pick the variables. Here quiet goes across as a switch called "Quiet mode" and message as a text called "Panel message".

Press enter or click to view image in full size
Two of the panel’s own values, announced as a switch and a text.

A sensor or binary sensor is only read. A switch, number or text can also be set from Home Assistant: the panel listens on the entity’s own /set topic, so flicking "Quiet mode" in Home Assistant moves the switch on the wall. The panel also gets a status topic, so Home Assistant greys its entities out while it's unplugged.

Once the board connects, it should appear under Settings > Devices & services > MQTT as “Hall panel”. Nothing is announced before that first connection, so don’t go looking for it while the board is still in its box.

This bit is part of LCD Wizard Pro. Connecting, listening, publishing and importing are free on every plan, and the export dialog tells you which parts of a design are Pro before you generate anything.

Press enter or click to view image in full size
The export dialog names the Pro part of the design.

Try it before you flash it

Preview plays the design in the browser, with every label reading its topic’s sample message. Press On and the Console shows what the board would publish. The designer doesn’t send it, so you can’t switch your real porch light from the browser by accident.

Press enter or click to view image in full size
“ON” on house/light/porch/set. The board says it, the designer doesn’t.

Then export, build and upload with PlatformIO or the Arduino IDE. The MQTT client is the one in the ESP32’s own core, so there’s no library to install.

Devices that aren’t on MQTT

Plenty of kit reaches Home Assistant some other way (Hue, Nest, ZHA, cloud integrations) and says nothing on the broker. Home Assistant can put them there for you with MQTT Statestream:

mqtt_statestream:
base_topic: homeassistant_states
include:
entities:
- light.kitchen
- sensor.living_room_temperature

After a restart each entity’s state appears, retained, on topics like homeassistant_states/light/kitchen/state. Statestream only speaks, though. To switch the kitchen light from the panel, publish to a topic of your own and let an automation do the switching:

automation:
- alias: Panel switches the kitchen light
triggers:
- trigger: mqtt
topic: panel/kitchen/set
actions:
- action: "light.turn_{{ 'on' if trigger.payload == 'ON' else 'off' }}"
target:
entity_id: light.kitchen

More than one broker

The panel connects to one broker, and so does Home Assistant. If some of your kit lives on another one, bridge it into yours with a few lines of Mosquitto config, then point the panel at the main broker:

connection garage
address 192.168.1.50:1883
remote_username bridge
remote_password a-password
topic zigbee2mqtt/# both 0

When it doesn’t work

  • Nothing arrives and the address ends in .local. The board doesn’t look those names up. Use the numbers.
  • Nothing arrives and the address has :8123 in it. That’s Home Assistant’s website. The broker is port 1883.
  • The broker turns the panel away. Try the same login from MQTT Wizard. With your own Mosquitto, restart it after adding a user.
  • TLS is ticked and it won’t connect. A home broker with a certificate you made yourself needs that certificate pasted in. Most home brokers use plain 1883 on the local network anyway.
  • The panel isn’t in Home Assistant. It announces only after it has connected, and Home Assistant has to be on the same broker with discovery turned on.
  • A value is always 0 or blank. Check the type and the JSON path on the Topics tab, and remember topics are case sensitive.

Have a go

The designer is at lcdwizard.com, and the full step-by-step version of this, with every click and all 32 pictures, is at lcdwizard.com/docs/tutorial-mqtt-home-assistant. If you build one, tell us how it went on the forum. A photo of it on a real wall would make my week.

--

--