Skip to content

Repository files navigation

esphome-components

Reusable ESPHome external components for grow and environmental monitoring hardware — a thermal imaging camera, derived statistics and threshold alerting for CO₂ sensors, typed support for liquid chemistry probes, and M5Stack CoreS3 board support.

This repository owns components only. It contains no device firmware — real per-device configs live in a separate fleet repository (grow-fleet) and pull these components in by reference. Each component is independent and can be adopted à la carte.

Component catalog

Component What it does Docs
mlx90640 Melexis MLX90640 32×24 thermal camera: per-pixel temperatures, min/max/avg and region-of-interest (ROI) stats, configurable emissivity/refresh/resolution, color palettes, and a self-contained thermal-viewer web page (plus on-demand JPEG renders) served over HTTP. README · example
m5stack_thermal2 M5Stack Unit Thermal2 (MLX90640 behind a PICO-D4 at 0x32): whole-frame + off-center ROI temperature stats, a /thermal.jpg image, plus a software temperature alarm that beeps the unit's buzzer and flashes its RGB red (with a mute switch and button-driven ROI toggle). Sibling to mlx90640, for the newer smart unit. README · example
scd4x_stats Derived sensors for an SCD4x CO₂ sensor: VPD (vapor-pressure deficit), daily min/max, and moving averages, with a midnight reset. README
scd4x_alerts Debounced threshold alerting over CO₂, temperature, humidity, and VPD. Emits binary_sensor alert outputs with user-adjustable number thresholds and configurable on/off delays. README
ezo_types Typed support for Atlas Scientific EZO circuits (pH, EC, RTD, ORP). A multi-platform component (sensor/select/number/switch) with diagnostic sensors, calibration controls, and temperature-compensated reads. README
qmp6988 Hardened drop-in replacement for ESPHome's built-in QMP6988 barometric pressure sensor: verifies the device entered measuring mode (with retries), self-heals at runtime if it stops converting, and guards against publishing physically impossible values. Same schema as upstream. README · example
board_m5cores3 M5Stack CoreS3 board bring-up: powers the AXP2101 PMIC, configures the AW9523 GPIO expander, and enables the display backlight — prerequisites before anything renders.
m5cores3_power Polls the AXP2101 PMIC for battery / power state.
m5cores3_touch Drives the CoreS3 touchscreen and fires touch/release automation triggers.
m5cores3_display Renders environmental data and a color-mapped thermal image to the built-in CoreS3 screen, refreshing only changed values each loop.
m5dial_spectrum Live, wavelength-colored spectrum chart drawn inside an LVGL container — fills the gap where ESPHome's LVGL has no chart widget and no templatable geometry. Updates only the bars that changed. Built for the M5Stack Dial's round 240×240 panel. README · example
grow_env_monitor Integrative component that composes the others — thermal camera, CO₂/temp/humidity with derived VPD, threshold alerts, light status, and ROI stats — and renders the full picture to the CoreS3 display.

Architecture

Every component follows ESPHome's external-component convention and is built in two layers:

  • Python codegen (__init__.py and the platform modules sensor.py, select.py, number.py, switch.py). These define a CONFIG_SCHEMA that validates user YAML and a to_code() that emits the C++ wiring. This Python runs on your build machine, not on the device — it generates firmware source.
  • C++ firmware (*.h / *.cpp). The on-device implementation the codegen instantiates and wires together — polling sensors, computing derived values, driving peripherals, and serving HTTP.

The mlx90640 component additionally delegates to vendored Melexis driver code (MLX90640_API.* for frame acquisition, EEPROM calibration, and temperature math) behind a thin I²C shim (MLX90640_I2C_Driver.*) that adapts the upstream driver onto an ESPHome i2c::I2CBus. The API files are essentially untouched upstream code; the shim is the integration seam this repo owns.

The components are intentionally decoupled — there are no cross-component imports. grow_env_monitor composes the others through ESPHome configuration, not code dependencies, so you can use any single component on its own.

Repository layout

<component>/
  __init__.py          # ESPHome codegen entry point (CONFIG_SCHEMA + to_code)
  sensor.py …          # additional platform modules, where applicable
  <component>.h/.cpp   # on-device C++ implementation
  README.md            # per-component config reference (where present)
docker/                # local ESPHome dev harness (see below)

Using these components

Components live at the repository root (not in a components/ subfolder), which matters for how you reference them.

Local source (recommended)

How the dev harness and the fleet repo consume them — vendor this repo (clone or git submodule) and point ESPHome at the checkout:

external_components:
  - source:
      type: local
      path: /path/to/esphome-components
    components: [mlx90640, scd4x_stats, scd4x_alerts]   # only what you use

Git source

For external projects pulling directly from GitHub. Because components sit at the repo root, set path: .:

external_components:
  - source:
      type: git
      url: https://github.com/dephekt/esphome-components
      path: .
    components: [mlx90640]

Most components are I²C devices, so a standard ESPHome i2c: bus is a prerequisite. See each component's README and mlx90640/example.yaml for complete, copy-pasteable device configs.

Local development

A Dockerized ESPHome dev loop lives in docker/. It pins the ESPHome image (ghcr.io/esphome/esphome:2026.5), mounts this repo at /config, and exposes USB and host networking for flashing, OTA, and mDNS. Scratch configs reference the in-tree components via a type: local, path: /config source.

The docker/esphome wrapper runs the ESPHome CLI inside that container against the local Docker daemon (run from anywhere; config paths are relative to the repo root):

./docker/esphome config  mlx90640/example.yaml          # validate
./docker/esphome compile path/to/scratch.yaml           # build firmware
./docker/esphome run     path/to/scratch.yaml --device /dev/ttyACM0   # flash

Or run the ESPHome web dashboard:

docker compose -f docker/esphome-dev.yml up -d          # http://localhost:6052

License

Copyright (c) 2026 Daniel Snider.

This project is dual-licensed, mirroring the split upstream ESPHome uses:

Files License
C++ / runtime (.c, .cpp, .h, .hpp, .tcc, .ino) GPL-3.0-or-later
Python codegen, YAML examples, documentation MIT

The C++ is compiled and linked into the ESPHome firmware binary against ESPHome's own GPLv3 headers and base classes, so it is a derivative work and carries a compatible copyleft license. The Python codegen runs on the build machine against ESPHome's MIT-licensed Python codebase and is unencumbered.

Every source file carries an SPDX header naming which license applies. Full texts of both are in LICENSE; contribution terms are in CONTRIBUTING.md.

Third-party code

Path Origin License
mlx90640/MLX90640_API.* Melexis N.V. MLX90640 driver, vendored unmodified Apache-2.0
mlx90640/MLX90640_I2C_Driver.* Melexis N.V., modified to route I2C through ESPHome's bus Apache-2.0
qmp6988/* Derived from ESPHome's built-in qmp6988 component (hardened init, runtime self-heal, plausibility guard) GPL-3.0-or-later (C++) / MIT (Python)
ezo_types/ezo_base.* Derived from ESPHome's built-in ezo component (bounded command deadline, failure counting) GPL-3.0-or-later

Apache-2.0 is one-way compatible with GPLv3, so the Melexis driver combines cleanly into the GPL-licensed firmware while retaining its own terms.

About

My custom ESP32 firmware and ESPHome components.

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages