Skip to content

labodj/lsh-bridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lsh-bridge: ESP32 Bridge for Labo Smart Home

PlatformIO Registry CI Latest Release License

lsh-bridge is the ESP32 bridge runtime for the Labo Smart Home controller path. It talks to an lsh-core controller over UART, exposes the controller model over MQTT and Homie, and keeps the network-facing runtime synchronized with the physical panel.

The reference path documented here is one bridge per controller: a Controllino-style AVR device running lsh-core, an ESP32 running lsh-bridge, an MQTT broker, and the LSH coordinator or Node-RED logic layer above it.

If you are new to LSH as a whole, start with the labo-smart-home documentation map before tuning bridge settings.

For a first end-to-end installation, prefer the stack-generated path over copying capacity, topic and codec flags by hand:

lsh-stack new my-lsh-installation
cd my-lsh-installation
lsh-stack setup

That command creates the consumer PlatformIO projects and writes the bridge platformio-bridge.ini, coordinator config, Node-RED settings and deploy plan from the same controller TOML.

The main branch can move ahead of tagged releases. For downstream projects, prefer released tags unless you are intentionally testing coordinated unreleased work across the LSH repos.

What lsh-bridge Owns

lsh-bridge is intentionally narrow:

  • it reads and writes the controller serial protocol
  • it rebuilds the MQTT and Homie model from controller DEVICE_DETAILS
  • it publishes controller state, events and bridge diagnostics
  • it coalesces actuator command bursts before sending SET_STATE to the controller
  • it keeps a validated controller topology cache in ESP32 NVS
  • it asks the controller to resync after boot, MQTT recovery or topology changes

The bridge does not own physical I/O. Buttons, relays, indicators and local fallback remain controller responsibilities.

What You Need

For the documented bridge path:

  • PlatformIO
  • an ESP32 board supported by pioarduino/platform-espressif32
  • a controller running lsh-core
  • a hardware UART between controller and ESP32
  • a 5 V / 3.3 V level shifter when the controller UART is 5 V
  • an MQTT broker; the bridge publishes Homie v5 metadata from the controller topology

The bridge is optimized for a static controller topology. It can recover from a changed topology, but topology changes are expected to come from controller firmware updates or reboots rather than from devices appearing dynamically at runtime.

First Build

The practical starting reference is the bundled PlatformIO example:

platformio run -d examples/basic-homie-bridge -e release

The example also keeps CI-backed variants for codec and optimization coverage:

  • release: conservative first build
  • release_aggressive: more aggressive optimization profile
  • release_json_serial: JSON on the controller UART
  • release_msgpack_mqtt: MessagePack on serial and MQTT
  • release_json_serial_msgpack_mqtt: JSON on serial, MessagePack on MQTT

Keep the release profile for the first bring-up. Change codecs, topic names or capacity limits after the controller, bridge and MQTT path have worked once together.

Embed the Library

Install from the PlatformIO Registry:

lib_deps =
    labodj/lsh-bridge@^1.6.0

The embedding firmware owns board choice, serial pins, topic names, firmware identity and deployment policy. A minimal Arduino entry point looks like this:

#include <Arduino.h>
#include <lsh_bridge.hpp>

namespace {

lsh::bridge::BridgeOptions makeBridgeOptions() {
  lsh::bridge::BridgeOptions options;
  options.serial = &Serial2;
  options.disableLedFeedback = true;
  return options;
}

lsh::bridge::LSHBridge bridge(makeBridgeOptions());

}  // namespace

void setup() {
  bridge.begin();
}

void loop() {
  bridge.loop();
}

Leaving BridgeOptions::serial unset resolves to Serial2. By default, the bridge also disables Homie LED feedback, keeps ESP32 Wi-Fi modem sleep disabled and uses build-driven logging. Set the options explicitly when you want the firmware entry point to document those choices.

The full example lives in examples/basic-homie-bridge.

Hardware Integration

In the public panel pattern, the ESP32 bridge is paired one-to-one with the controller:

12/24 VDC supply
        |
        +-------------------------------> Controllino / lsh-core
        |
        +--> 5 V buck converter -------> ESP32 / lsh-bridge

Controller TTL UART
        |
        +--> 5 V / 3.3 V level shifter --> ESP32 UART

Common ground shared by controller, buck converter, level shifter and ESP32.

The bridge usually talks to the controller over a hardware UART rather than USB. On Controllino-style panels, the controller side is 5 V logic and the ESP32 side is 3.3 V logic, so the UART path needs a proper level shifter.

For panel-level power and wiring context, read the Labo Smart Home hardware overview.

Runtime Shape

+-------------+    serial    +------------+    MQTT    +--------------+
| lsh-core    | <----------> | lsh-bridge | <--------> | coordinator  |
| controller  |              | ESP32      |            | or Node-RED  |
+-------------+              +------------+            +--------------+

Runtime rules:

  • the controller remains authoritative for actuator state
  • the bridge caches only validated topology, never runtime actuator state
  • startup uses cached topology when available, then asks the controller for fresh details and state
  • device-topic PING answers controller reachability only when the runtime is synchronized
  • service-topic PING answers bridge reachability on the bridge-local topic
  • topology changes are saved to NVS and followed by one controlled reboot
  • retained, fragmented, oversize or malformed MQTT commands are rejected and diagnosed

For the detailed runtime story, read docs/runtime-behavior.md.

Configuration

Most bridge choices are compile-time PlatformIO flags because they affect fixed buffers, topic sizes, protocol codecs or Homie identity. The most common groups are:

  • capacities: CONFIG_MAX_ACTUATORS, CONFIG_MAX_BUTTONS, CONFIG_MAX_NAME_LENGTH
  • serial: CONFIG_ARDCOM_SERIAL_RX_PIN, CONFIG_ARDCOM_SERIAL_TX_PIN, CONFIG_ARDCOM_SERIAL_BAUD
  • MQTT topics: CONFIG_MQTT_TOPIC_BASE, CONFIG_MQTT_TOPIC_EVENTS, CONFIG_MQTT_TOPIC_BRIDGE, CONFIG_MQTT_TOPIC_SERVICE
  • Homie: HOMIE_CONVENTION_VERSION=5, CONFIG_HOMIE_FIRMWARE_NAME, CONFIG_HOMIE_FIRMWARE_VERSION, CONFIG_HOMIE_BRAND
  • runtime policy: queue capacity, command coalescing windows, topology reboot timing and reset-trigger policy
  • codecs: CONFIG_MSG_PACK_ARDUINO and CONFIG_MSG_PACK_MQTT

Use the bundled example as the starting point. The complete reference lives in docs/compile-time-configuration.md.

For full-stack installations, prefer generating these flags from the controller contract with the labo-smart-home stack composer. The generated platformio-bridge.ini creates one wide bridge firmware environment per profile. Device names are upload targets, not firmware variants:

[platformio]
extra_configs = generated/platformio-bridge.ini
platformio run -e bridge_littlefs
platformio run -e bridge_littlefs_usb_j1 -t upload

In the one-project workflow, lsh-bridge stays a normal PlatformIO dependency. The generated environments remove the need to copy capacity, topic and codec flags by hand, and persistent local extensions can live outside generated/. Firmware OTA for this bridge is MQTT/Homie-based: use the stack-generated LSH OTA <device> custom targets or the generated deploy-plan.json command for your MQTT OTA helper.

Documentation

Compatibility

Validated baseline:

  • ESP32
  • Arduino framework
  • pioarduino/platform-espressif32
  • Homie convention v5 through labodj/homie-v5

Recommended PlatformIO platform:

platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
framework = arduino
board = esp32dev

stable is a moving platform alias. Validate every lsh-bridge release against the current platform before deployment.

OTA updates only the application image (firmware.bin). It does not update bootloader, partition table or other full-flash artifacts. If the ESP32 platform update changes those artifacts, validate them explicitly and use a full USB/serial flash when required.

This repository targets ESP32. ESP8266 support would need separate validation and support work.

Maintainer Notes

Maintainer workflow notes live in DOCS.md. Package smoke and release publishing use platformio pkg pack, so exported Markdown uses absolute links rather than repository-relative links.

About

Reusable ESP32 bridge runtime for the LSH ecosystem, connecting serial controllers to MQTT and Homie.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages