Compare commits

..
42 Commits
Author SHA1 Message Date
randy 3374ed6ad8 staircase-light: add second PIR sensor
CI / ESPHome config validation (push) Failing after 5s
CI / YAML lint (push) Failing after 19s
2026-10-10 17:50:24 +02:00
randy e5f9c5813e stackchan: 40MHz flash, the IDF 5.5.5 bootloader misreads this flash at 80MHz 2026-10-10 17:41:05 +02:00
randy 2b66f1a60d echo-1: WAV media format, decoding MP3/FLAC without PSRAM runs the heap out 2026-10-10 17:41:05 +02:00
randy 05060756e3 OpenPrintTag reader: filament color light falls back to the Creality tag
CI / ESPHome config validation (push) Failing after 6s
CI / YAML lint (push) Failing after 17s
2026-10-10 12:35:49 +02:00
randy 7cc90187d1 ipv6_only_eth: mdns 1.14.0 from the registry instead of the fork 2026-10-10 12:35:49 +02:00
randy 26a09b37bc all esp8266: LEAmDNS fork announcing IPv6 addresses (esp8266/Arduino#9068) 2026-10-10 12:33:12 +02:00
randy 4c45ebdc4a all esp32: disable wifi power saving
CI / YAML lint (push) Successful in 8s
CI / ESPHome config validation (push) Successful in 1m2s
2026-10-08 22:52:25 +02:00
randy 2ad74b9d05 all esp8266: switch to native toolchain 2026-10-08 22:51:21 +02:00
randy b1b57818df fireplace, heater: switch to native ds248x component + cleanup 2026-10-08 22:50:00 +02:00
randy 1a83052d90 Spool reader: Creality CFS tags too
CI / YAML lint (push) Successful in 9s
CI / ESPHome config validation (push) Successful in 57s
creality_cfs reads the Creality tags of the spools, sends their record
to Home Assistant (esphome.creality_cfs) and writes them through the
creality_cfs_write action; the success tune gets a valid default
duration.
2026-10-05 21:22:36 +02:00
randy 8eae480253 OpenPrintTag reader: pn5180 and openprinttag components, red flash on writes
CI / YAML lint (push) Failing after 17s
CI / ESPHome config validation (push) Successful in 55s
The reader config follows the split of pn5180 into the reader and the
openprinttag component; the notify LED flashes red while the
integration writes to a tag.
2026-10-03 18:18:42 +02:00
randy 5fdacb82df OpenPrintTag reader: aux write action for the integration
CI / YAML lint (push) Failing after 17s
CI / ESPHome config validation (push) Successful in 51s
openprinttag_write_aux lets the OpenPrintTag integration's
openprinttag.update write the consumed weight and other aux values
to the tag on the reader.
2026-10-03 13:55:21 +02:00
randy 9eb5cd9155 OpenPrintTag reader: send the tag record to Home Assistant
esphome.openprinttag event with the uid and the raw record (empty when
the tag is removed) for the OpenPrintTag integration
(randybb/ha-openprinttag).
2026-10-03 13:20:40 +02:00
randy b8f8649833 OpenPrintTag reader: M5Stamp S3 with a PN5180
Filament spool tags to Home Assistant through the pn5180 component of
randybb/esphome-components, the color also as a light. Onboard LED for
tag feedback and status until the external LED is fitted, buzzer on
GPIO4.
2026-10-03 12:48:56 +02:00
randy 5fdea643a7 rfid-reader: use a valid RTTTL default duration (d=32)
ESPHome only accepts d=1/2/4/8/16/32 now; d=24 was rejected and the
success/write tones never played.
2026-10-03 10:51:23 +02:00
randy 4bbf26fc87 Update comment about upstream mdns component
CI / YAML lint (push) Failing after 17s
CI / ESPHome config validation (push) Successful in 1m0s
2026-10-02 17:46:59 +02:00
randy 427e9ac136 IPv6-only for the Ethernet gateway
Split the WiFi part off common/ipv6_only.yaml into common/ipv6_only_eth.yaml
and use it on mcu-gateway. The #19750 component list needs ethernet,
otherwise the stock component still runs DHCPv4. mdns from the fork also
carries the IPv6 fix for ETH-only builds (espressif/esp-protocols#1161).
2026-10-01 23:49:02 +02:00
randy 005c9903bf Disable api reboot timeout for kitchen lights due flaky wifi (thanks ubiquiti!)
CI / YAML lint (push) Failing after 17s
CI / ESPHome config validation (push) Successful in 51s
2026-10-01 12:37:09 +02:00
randy db57574497 Fix crashing, display cs and fonts for cnc pendant
CI / YAML lint (push) Failing after 18s
CI / ESPHome config validation (push) Successful in 49s
2026-10-01 01:38:21 +02:00
randy fd7a4c98b5 Add initial mcu-cnc-pendant configuration 2026-10-01 00:50:41 +02:00
randy 2e8b678072 nrf-ant, nrf-dk: two-way UART on the DK default pins, wires crossed
Both boards use UART1 RX P1.01 / TX P1.02 so Home Assistant data can reach
the ANT+ node's transmitters; on the default pins the ANT+ node no longer
needs the RX pin workaround.
2026-09-30 23:15:10 +02:00
randy 3f9a8c3117 nrf-ant: Garmin HRM-Dual, HRM-Tri, Rally RS200, Speed Sensor 2, SRAM Force AXS
CI / YAML lint (push) Successful in 8s
CI / ESPHome config validation (push) Successful in 50s
Also sets the unused UART1 RX to P1.02: without it the fork keeps the DK's
default RX pin, P1.01, and the UART hears its own transmissions.
2026-09-30 22:13:33 +02:00
randy 38ede7fab6 nrf-ant: Garmin HRM-Pro, Concept2 PM5, Garmin Tempe, Garmin Varia RTL515, status LEDs
LED 1 lights while a configured ANT+ device is received, LED 2 while an
unconfigured one is in range; everything is forwarded to mcu-nrf-dk.
2026-09-30 21:55:04 +02:00
randy ad9aeea346 nrf-dk: Thread MTD, frees 52 KB of the MCUboot slot (98 % -> 87 %) 2026-09-30 21:34:17 +02:00
randy 3a397cfb4b ANT+ via ESPHome: mcu-nrf-ant (RadiANT) sends heart rate to mcu-nrf-dk over packet_transport
Replaces the E73 running the archived nrf-ant-bridge firmware and drops
mcu-ant-host, which read that bridge's line protocol.
2026-09-30 21:17:20 +02:00
randy 6fd5ee1fa7 Add ant-host: host ESPHome reading an ANT+ bridge over serial 2026-09-30 20:07:57 +02:00
randy eb25302e9b nrf-dk: Thread, buttons, LEDs and ANT+ heart rate from the E73 bridge 2026-09-30 20:07:57 +02:00
randy 34929a38c7 CI: skip zephyr: configs, they need the esphomeplatformzephyr fork 2026-09-30 20:07:57 +02:00
randy 0536e91fd1 CI: work on Gitea's runner image too
CI / YAML lint (push) Successful in 5s
CI / ESPHome config validation (push) Successful in 10s
Install yamllint with pip instead of ibiqlik/action-yamllint, which expects
it preinstalled like on GitHub's runner, and pip install with
--ignore-installed so pip doesn't try to remove Debian's packages.
2026-09-30 14:50:33 +02:00
randy 7374ddf4d6 Drop the speaker override, esphome#19862 is merged
CI / YAML lint (push) Failing after 32s
CI / ESPHome config validation (push) Failing after 37s
2026-09-30 12:35:53 +02:00
randy a005b940b2 rfid-reader: take the NDEF records by reference
get_records() now returns a StaticVector of unique_ptr, which can't be copied.
2026-09-30 12:15:49 +02:00
randy 46cf3b1fe8 OTA: require encryption with the api key, plaintext + password only for migration
allow_plaintext_upload lets the uploader give a device that doesn't encrypt
yet its one migration install. Remove it together with the password once
every device has been updated (the uploader says so).
2026-09-30 12:05:39 +02:00
randy bb76912023 Set framework.advanced.flash_chip on ESP32 devices to save IRAM
Values come from ESPHome's own hint in the log of each online device
("Set flash_chip: ... to save IRAM"). Devices that were off got the value of
an identical board (ESP32-PICO-D4 ATOM/Stamp Pico: gd, JC3248W535: generic,
POW Elite: gd), marked as not read from the device.
2026-09-30 11:57:30 +02:00
randy 831d88689d CI: Node 24 actions, pip on PEP 668 runner images, drop committed build cache
- actions/checkout@v7 and tj-actions/changed-files@v47 (Node 20 is deprecated)
- PIP_BREAK_SYSTEM_PACKAGES for Gitea's runner image (externally-managed Python)
- untrack common/.esphome (a gitlink with no submodule mapping) and ignore
  .esphome/ in every directory
2026-09-30 11:21:55 +02:00
randy 170fd69274 Fix yamllint errors: trailing spaces, blank lines and newline at end of file
Allow aligned values after a colon (the bedroom lamp presets).
2026-09-30 11:08:22 +02:00
randy 89763817f6 bedroom lamps: use the xiaomi_bslamp2 fork with the ESPHome 2026.10 light fix 2026-09-30 10:53:16 +02:00
randy 03ca4e98b5 status_led: show component errors only on a dedicated status LED (show_errors)
The ATOM LED gets them; displays and lights that are also normal lights don't,
so a failed component can't take them over.
2026-09-30 10:12:06 +02:00
randy fb66547dd1 status_led: don't show component errors, only network, API and OTA 2026-09-30 09:00:58 +02:00
randy 725c400de6 atoms3: full-screen status, IPv6-only, animation as image platform, fix colours
The status (common/status_led.yaml) drives a virtual RGB light that fills
the display; the display needs little-endian RGB565 (colours were swapped).
2026-09-30 08:58:16 +02:00
randy 7517c301ac Status LED on every ATOM device (except the vehicle beacons)
common/status_led_atom.yaml puts common/status_led.yaml on the ATOM Lite's
own RGB LED (G27, 64 RMT symbols to leave room for IR/RF). echo-1 uses its
existing LED light.
2026-09-30 08:58:16 +02:00
randy 422b334582 air-office-r: LEDs back on (the stick had lost its GND), status on the NEO stick 2026-09-30 08:29:19 +02:00
randy 2f5e438424 Move remaining NSPanel's to IPv6 Only network 2026-09-30 08:08:12 +02:00
70 changed files with 116855 additions and 232 deletions

No files matched your search

+18 -9
View File
@@ -10,35 +10,42 @@ jobs:
name: YAML lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: Get changed YAML files
id: changed
uses: tj-actions/changed-files@v46
uses: tj-actions/changed-files@v47
with:
files: "**/*.yaml"
- uses: ibiqlik/action-yamllint@v3
# yamllint straight from pip: Gitea's runner image doesn't ship it like GitHub's does
- name: Lint changed YAML files
if: steps.changed.outputs.any_changed == 'true'
with:
config_file: .yamllint.yml
file_or_dir: ${{ steps.changed.outputs.all_changed_files }}
env:
PIP_BREAK_SYSTEM_PACKAGES: "1"
run: |
pip install --ignore-installed yamllint
yamllint -c .yamllint.yml -f parsable ${{ steps.changed.outputs.all_changed_files }}
validate:
name: ESPHome config validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: Get changed device configs
id: changed
uses: tj-actions/changed-files@v46
uses: tj-actions/changed-files@v47
with:
files: "mcu-*.yaml"
- name: Install ESPHome (dev)
if: steps.changed.outputs.any_changed == 'true'
run: pip install git+https://github.com/esphome/esphome.git@dev
# Gitea's runner image marks the system Python as externally managed (PEP 668)
# and has Debian packages pip can't uninstall (pyparsing), so don't touch them
env:
PIP_BREAK_SYSTEM_PACKAGES: "1"
run: pip install --ignore-installed git+https://github.com/esphome/esphome.git@dev
- name: Prepare secrets
if: steps.changed.outputs.any_changed == 'true'
@@ -48,6 +55,8 @@ jobs:
if: steps.changed.outputs.any_changed == 'true'
run: |
for f in ${{ steps.changed.outputs.all_changed_files }}; do
# zephyr: needs the esphomeplatformzephyr fork, upstream doesn't know it yet
if grep -q '^zephyr:' "$f"; then echo "Skipping $f (zephyr fork)"; continue; fi
echo "Validating $f..."
esphome config "$f"
done
+1 -1
View File
@@ -2,7 +2,7 @@
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.claude/
/.esphome/
.esphome/
/secrets.yaml
/archive/
/trash/
+4
View File
@@ -25,3 +25,7 @@ rules:
comments:
require-starting-space: false
# Aligned values (e.g. the bedroom lamp presets) are intentional
colons:
max-spaces-after: -1
+28781
View File
File diff suppressed because it is too large. Load diff
+86576
View File
File diff suppressed because it is too large. Load diff
Submodule common/.esphome/external_components/b7dc7eea deleted from 16571e8a90.
+10
View File
@@ -0,0 +1,10 @@
---
# ESP8266 core with LEAmDNS announcing the IPv6 addresses (AAAA, ff02::fb) from
# randybb/Arduino@mdns-ipv6-aaaa (esp8266/Arduino#9068); add next to common_esp8266.yaml.
# The device must not set 'toolchain: arduino' (no custom framework source there).
# Drop once it's upstream and in an ESPHome release.
esp8266:
toolchain: platformio
framework:
version: 3.1.2
source: https://github.com/randybb/Arduino.git#mdns-ipv6-aaaa
+3 -23
View File
@@ -3,32 +3,12 @@
# packages:
# common: !include common/common.yaml
# ipv6_only: !include common/ipv6_only.yaml
external_components:
# network enable_ipv4 + audio HTTP reader over IPv6 (esphome/esphome#19750), drop once merged
- source: github://pr#19750
components: [const, network, wifi, audio]
# Ethernet devices use common/ipv6_only_eth.yaml (this without the WiFi part)
packages:
base: !include ipv6_only_eth.yaml
wifi:
networks:
- id: !extend wifi_iot
ssid: !secret wifi_ssid_ipv6
password: !secret wifi_password_ipv6
esp32:
framework:
components:
# mdns 1.12.0 + fix for "A 0.0.0.0" without IPv4 (espressif/esp-protocols PR pending), drop once released
- name: espressif/mdns
source: https://github.com/randybb/esp-protocols.git
ref: mdns-v1.12.0-zero-ipv4-test
path: components/mdns
# IDF v5.5.5 lwip + .local resolution over IPv6 (espressif/esp-lwip#94), drop once in IDF
- name: lwip
source: https://github.com/randybb/esp-lwip.git
ref: idf-v5.5.5-lwip-component
path: lwip
network:
enable_ipv6: true
enable_ipv4: false
min_ipv6_addr_count: 1
+29
View File
@@ -0,0 +1,29 @@
---
# IPv6-only IoT network (SLAAC, no DHCPv4) for ethernet devices; add next to a common package:
# packages:
# common_eth: !include common/common_eth.yaml
# ipv6_only: !include common/ipv6_only_eth.yaml
# WiFi devices use common/ipv6_only.yaml (this + the IPv6 SSID)
external_components:
# network enable_ipv4 + audio HTTP reader over IPv6 (esphome/esphome#19750), drop once merged
- source: github://pr#19750
components: [const, network, wifi, ethernet, audio]
refresh: 1h
esp32:
framework:
components:
# mdns 1.14.0: no "A 0.0.0.0" without IPv4 + IPv6 on ETH-only builds (espressif/esp-protocols#1156, #1161),
# drop once on ESPHome 2026.10.0 (esphome/esphome#20383 bumps the pin from 1.12.0)
- name: espressif/mdns
ref: 1.14.0
# IDF v5.5.5 lwip + .local resolution over IPv6 (espressif/esp-lwip#94), drop once in IDF
- name: lwip
source: https://github.com/randybb/esp-lwip.git
ref: idf-v5.5.5-lwip-component
path: lwip
network:
enable_ipv6: true
enable_ipv4: false
min_ipv6_addr_count: 1
+1
View File
@@ -28,6 +28,7 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: generic
minimum_chip_revision: 3.0
sram1_as_iram: true
+4
View File
@@ -2,3 +2,7 @@
ota:
- platform: esphome
password: !secret ota_password
# migration to encrypted OTA (api key): once every device encrypts,
# remove allow_plaintext_upload together with the password
encryption:
allow_plaintext_upload: true
+4
View File
@@ -3,4 +3,8 @@ ota:
- platform: esphome
id: ota_esphome
password: !secret ota_password
# migration to encrypted OTA (api key): once every device encrypts,
# remove allow_plaintext_upload together with the password
encryption:
allow_plaintext_upload: true
allow_partition_access: true
-1
View File
@@ -7,4 +7,3 @@ accuracy_decimals: 2
update_interval: 60s
filters:
- lambda: return x / 86400;
+5 -4
View File
@@ -2,7 +2,7 @@
# Status on a visible RGB light, which stays a normal light otherwise:
# network down red, slow blink
# no API client (HA) orange, slow blink
# component error purple, steady
# component error purple, steady (only with show_errors: "true", for a dedicated status LED)
# OTA blue, fast blink; green when done, 3 red blinks on error
# back to normal green for 1 s, then the light goes back to how it was
# packages:
@@ -13,6 +13,7 @@
# Needs the ota id ota_esphome (common/ota_esp32.yaml).
defaults:
brightness: "0.3"
show_errors: "false" # a failed component would take over a display or a shared light for good
globals:
- id: status_led_active
@@ -72,14 +73,14 @@ interval:
static uint8_t tick = 0;
tick++;
bool slow = (tick / 2) % 2 == 0; // 1 s on, 1 s off
bool problem = !network::is_connected() || !api::global_api_server->is_connected() ||
(App.get_app_state() & STATUS_LED_ERROR);
bool error = ${show_errors} && (App.get_app_state() & STATUS_LED_ERROR);
bool problem = !network::is_connected() || !api::global_api_server->is_connected() || error;
if (problem) id(status_led_restore)->stop();
if (!network::is_connected()) {
id(status_led_show)->execute(1.0f, 0.0f, 0.0f, slow);
} else if (!api::global_api_server->is_connected()) {
id(status_led_show)->execute(1.0f, 0.4f, 0.0f, slow);
} else if (App.get_app_state() & STATUS_LED_ERROR) {
} else if (error) {
id(status_led_show)->execute(0.6f, 0.0f, 1.0f, true);
} else if (id(status_led_active) && !id(status_led_restore)->is_running()) {
id(status_led_restore)->execute(true);
+19
View File
@@ -0,0 +1,19 @@
---
# Status LED on the M5Stack ATOM Lite's own RGB LED (G27), see common/status_led.yaml
packages:
status_led: !include
file: status_led.yaml
vars:
light_id: atom_led
show_errors: "true" # dedicated status LED
light:
- platform: esp32_rmt_led_strip
id: atom_led
internal: true
pin: 27
num_leds: 1
rmt_symbols: 64 # 1 LED is 24 bits; leave RMT memory for remote_transmitter/receiver
chipset: ws2812
channel_colors: GRB
restore_mode: ALWAYS_OFF
+2
View File
@@ -2,6 +2,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd # ESP32-PICO-D4, like every other ATOM Lite
type: esp-idf
external_components:
+1
View File
@@ -9,3 +9,4 @@ wifi:
enable_btm: true
enable_rrm: true
min_auth_mode: WPA3
power_save_mode: none
+148
View File
@@ -0,0 +1,148 @@
#pragma once
// Moonraker client for mcu-cnc-pendant on its own FreeRTOS task: esp_http_client blocks
// (DNS is not bounded by timeout_ms), so the main loop only queues commands and reads
// the last polled status. An unreachable Klipper shows as "offline" instead of starving
// the loop into the task watchdog.
#include <deque>
#include <mutex>
#include <string>
#include "esp_http_client.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esphome/components/json/json_util.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
namespace moonraker {
struct Status {
float pos[3]{};
std::string homed;
std::string state{"offline"};
};
class Client {
public:
void start(const char *base) {
this->base_ = base;
xTaskCreate(task, "moonraker", 6144, this, 1, nullptr);
}
// Run G-code; dropped when Klipper is not keeping up.
void gcode(const std::string &script) {
JsonDocument doc;
doc["script"] = script;
std::string body;
serializeJson(doc, body);
this->post("/printer/gcode/script", body);
}
// urgent: throw away everything queued and send this first (emergency stop)
void post(const std::string &path, const std::string &body = "", bool urgent = false) {
std::lock_guard<std::mutex> lock(this->mutex_);
if (urgent) {
this->queue_.clear();
} else if (this->queue_.size() >= MAX_QUEUE) {
return;
}
this->queue_.emplace_back(path, body);
}
Status status() {
std::lock_guard<std::mutex> lock(this->mutex_);
return this->status_;
}
protected:
static constexpr size_t MAX_QUEUE = 8;
static constexpr uint32_t POLL_MS = 250;
static constexpr int TIMEOUT_MS = 1000;
static void task(void *arg) {
auto *self = static_cast<Client *>(arg);
uint32_t last_poll = 0;
for (;;) {
std::pair<std::string, std::string> cmd;
bool have_cmd = false;
{
std::lock_guard<std::mutex> lock(self->mutex_);
if (!self->queue_.empty()) {
cmd = std::move(self->queue_.front());
self->queue_.pop_front();
have_cmd = true;
}
}
if (have_cmd) {
int code = self->request(cmd.first, &cmd.second, nullptr);
if (code != 200)
ESP_LOGW("moonraker", "POST %s failed (%d): %s", cmd.first.c_str(), code, cmd.second.c_str());
continue; // drain commands before the next poll
}
if (esphome::millis() - last_poll >= POLL_MS) {
last_poll = esphome::millis();
self->poll();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void poll() {
std::string body;
Status s;
if (this->request("/printer/objects/query?gcode_move=gcode_position&toolhead=homed_axes&print_stats=state",
nullptr, &body) == 200) {
auto doc = esphome::json::parse_json(body);
JsonObject st = doc["result"]["status"];
JsonArray p = st["gcode_move"]["gcode_position"];
for (int i = 0; i < 3; i++)
s.pos[i] = p[i];
s.homed = st["toolhead"]["homed_axes"].as<std::string>();
s.state = st["print_stats"]["state"].as<std::string>();
} else {
std::lock_guard<std::mutex> lock(this->mutex_);
s.pos[0] = this->status_.pos[0]; // keep the last position, only flag offline
s.pos[1] = this->status_.pos[1];
s.pos[2] = this->status_.pos[2];
}
std::lock_guard<std::mutex> lock(this->mutex_);
this->status_ = std::move(s);
}
// POST when body is set, GET otherwise; returns the HTTP status or -1
int request(const std::string &path, const std::string *body, std::string *out) {
std::string url = this->base_ + path;
esp_http_client_config_t cfg{};
cfg.url = url.c_str();
cfg.timeout_ms = TIMEOUT_MS;
cfg.method = body ? HTTP_METHOD_POST : HTTP_METHOD_GET;
esp_http_client_handle_t c = esp_http_client_init(&cfg);
if (c == nullptr)
return -1;
int code = -1;
int len = body ? body->size() : 0;
if (len > 0)
esp_http_client_set_header(c, "Content-Type", "application/json");
if (esp_http_client_open(c, len) == ESP_OK && (len == 0 || esp_http_client_write(c, body->data(), len) == len)) {
esp_http_client_fetch_headers(c);
code = esp_http_client_get_status_code(c);
char buf[256];
int n;
while (out != nullptr && (n = esp_http_client_read(c, buf, sizeof(buf))) > 0)
out->append(buf, n);
}
esp_http_client_cleanup(c);
return code;
}
std::string base_;
std::mutex mutex_;
std::deque<std::pair<std::string, std::string>> queue_;
Status status_;
};
inline Client client;
} // namespace moonraker
+59 -54
View File
@@ -3,7 +3,7 @@
# Pinout:
# GPIO21 PM1006 UART -> particle_uart (uart tx_pin)
# GPIO22 PM1006 UART -> particle_uart (uart rx_pin)
# GPIO25 TZT 8-bit WS2812 5050 stick (8 LEDs, 7 visible outside; LEDs 1-7 broken), disabled
# GPIO25 TZT 8-bit WS2812 5050 stick (8 LEDs, 7 visible outside) -> NEO [neo] (light esp32_rmt_led_strip), also status
# GPIO27 Onboard RGB LED (1x WS2812, inside), unused
# GPIO32 Grove SDA -> i2c (i2c sda)
# GPIO33 Grove SCL -> i2c (i2c scl)
@@ -24,10 +24,16 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
status_led: !include
file: common/status_led.yaml
vars:
light_id: neo
i2c:
# - id: i2c0
@@ -53,59 +59,58 @@ uart:
# number: 39
# inverted: true
# LEDs disabled until the stick is fixed (LEDs after the first one light up randomly)
# light:
# # only the first LED of the stick: the rest get garbage (broken DOUT after LED 0)
# - platform: esp32_rmt_led_strip
# name: NEO
# id: neo
# channel_colors: GRB
# pin: 25
# num_leds: 1
# chipset: ws2812
# restore_mode: ALWAYS_OFF
# effects:
# - random:
# - random:
# name: "My Slow Random Effect"
# transition_length: 30s
# update_interval: 30s
# - random:
# name: "My Fast Random Effect"
# transition_length: 4s
# update_interval: 5s
# - strobe:
# - strobe:
# name: Strobe Effect With Custom Values
# colors:
# - state: True
# brightness: 100%
# red: 100%
# green: 90%
# blue: 0%
# duration: 500ms
# - state: False
# duration: 250ms
# - state: True
# brightness: 100%
# red: 0%
# green: 100%
# blue: 0%
# duration: 500ms
# - flicker:
# - flicker:
# name: Flicker Effect With Custom Values
# alpha: 95%
# intensity: 1.5%
# - addressable_rainbow:
# - addressable_rainbow:
# name: Rainbow Effect With Custom Values
# speed: 10
# width: 50
# - addressable_scan:
# - addressable_scan:
# name: Scan Effect With Custom Values
# move_interval: 100ms
light:
# also the status light (common/status_led.yaml): back to its previous state when all is fine
- platform: esp32_rmt_led_strip
name: NEO
id: neo
channel_colors: GRB
pin: 25
num_leds: 7 # 8 on the stick, the 8th one is hidden
chipset: ws2812
restore_mode: ALWAYS_OFF
effects:
- random:
- random:
name: "My Slow Random Effect"
transition_length: 30s
update_interval: 30s
- random:
name: "My Fast Random Effect"
transition_length: 4s
update_interval: 5s
- strobe:
- strobe:
name: Strobe Effect With Custom Values
colors:
- state: True
brightness: 100%
red: 100%
green: 90%
blue: 0%
duration: 500ms
- state: False
duration: 250ms
- state: True
brightness: 100%
red: 0%
green: 100%
blue: 0%
duration: 500ms
- flicker:
- flicker:
name: Flicker Effect With Custom Values
alpha: 95%
intensity: 1.5%
- addressable_rainbow:
- addressable_rainbow:
name: Rainbow Effect With Custom Values
speed: 10
width: 50
- addressable_scan:
- addressable_scan:
name: Scan Effect With Custom Values
move_interval: 100ms
sensor:
# https://blissair.com/what-is-pm-2-5.htm
+2
View File
@@ -26,6 +26,8 @@ esp32:
flash_size: 8MB
toolchain: esp-idf
framework:
advanced:
flash_chip: generic
type: esp-idf
packages:
+40 -3
View File
@@ -42,6 +42,8 @@ esp32:
flash_size: 8MB
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
ota:
@@ -52,12 +54,14 @@ pcf8574:
address: 0x21
pcf8575: true
animation:
- file: "assets/images/blinky.gif"
image:
- platform: animation
file: "assets/images/blinky.gif"
id: blinky
resize: 128x128
type: RGB565
- file: "assets/images/vault_boy_walking.gif"
- platform: animation
file: "assets/images/vault_boy_walking.gif"
id: vaultboy
resize: 168x121
type: RGB565
@@ -127,6 +131,11 @@ external_components:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include
file: common/status_led.yaml
vars:
light_id: status_frame
# common: !include common/common_wo_debug.yaml
# common: !include common/common_dev.yaml
@@ -230,12 +239,32 @@ output:
- platform: ledc
pin: 16
id: gpio_tft_backlight
# virtual RGB light for common/status_led.yaml, shown full screen on the display
- platform: template
id: status_frame_r
type: float
write_action: []
- platform: template
id: status_frame_g
type: float
write_action: []
- platform: template
id: status_frame_b
type: float
write_action: []
light:
- platform: monochromatic
id: display_tft_backlight
output: gpio_tft_backlight
restore_mode: ALWAYS_ON
- platform: rgb
id: status_frame
internal: true
red: status_frame_r
green: status_frame_g
blue: status_frame_b
restore_mode: ALWAYS_OFF
switch:
- platform: template
@@ -391,6 +420,7 @@ display:
- platform: mipi_spi
model: ST7789V
id: display_tft
byte_order: little_endian # colours were byte-swapped (purple showed as green)
dimensions:
height: 128
width: 128
@@ -403,11 +433,18 @@ display:
# eightbitcolor: true
update_interval: 1s
lambda: |-
// status screen (common/status_led.yaml): the whole display in the status colour
auto &sv = id(status_frame)->current_values;
if (sv.is_on()) {
it.fill(Color(sv.get_red() * 255, sv.get_green() * 255, sv.get_blue() * 255));
return;
}
//Ingress shown animation Frame.
id(blinky).next_frame();
// Draw the animation my_animation at position [x=0,y=0]
it.image(0, 0, id(blinky), COLOR_ON, COLOR_OFF);
// // it.print(0, 0, id(font_default), "Hello World!");
// // it.strftime(0, 0, id(font_default), TextAlign::TOP_LEFT, "%H:%M", id(ha_time).now());
// it.rectangle(0, 0, it.get_width(), it.get_height(), id(my_blue));
+1
View File
@@ -25,6 +25,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
status_led:
pin:
+1
View File
@@ -24,6 +24,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
globals:
- id: aerator_auto
+5 -2
View File
@@ -39,18 +39,21 @@ esp32:
sdkconfig_options:
CONFIG_FREERTOS_UNICORE: y
advanced:
flash_chip: generic
ignore_efuse_custom_mac: true
ignore_efuse_mac_crc: true
external_components:
- source:
type: git
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
ref: dev
# fork: fix for ESPHome 2026.10 (restore_mode -> restore_state), back to mmakaay once merged
url: https://github.com/randybb/esphome-xiaomi_bslamp2
ref: fix-light-restore-state
refresh: 1h
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
# ------------------------------------------------------------------------
# Behavior: default
+5 -2
View File
@@ -39,18 +39,21 @@ esp32:
sdkconfig_options:
CONFIG_FREERTOS_UNICORE: y
advanced:
flash_chip: generic
ignore_efuse_custom_mac: true
ignore_efuse_mac_crc: true
external_components:
- source:
type: git
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
ref: dev
# fork: fix for ESPHome 2026.10 (restore_mode -> restore_state), back to mmakaay once merged
url: https://github.com/randybb/esphome-xiaomi_bslamp2
ref: fix-light-restore-state
refresh: 60s
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
# ------------------------------------------------------------------------
# Behavior: default
+2
View File
@@ -24,6 +24,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
type: esp-idf
external_components:
+2
View File
@@ -31,6 +31,8 @@ esp32:
variant: esp32c3
toolchain: esp-idf
framework:
advanced:
flash_chip: generic
type: esp-idf
# version: 5.4.2
# platform_version: 54.03.21
+2
View File
@@ -24,6 +24,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
type: esp-idf
external_components:
+235
View File
@@ -0,0 +1,235 @@
---
# Hardware: M5Stack M5Stamp S3 in the ESPendant case (github.com/positron96/ESP32_CNC_Pendant),
# talks to Klipper over Moonraker HTTP API
# Pinout:
# GPIO0 Stamp button (boot) -> stamp_button (binary_sensor gpio) (inverted)
# GPIO1 Handwheel A -> handwheel (sensor rotary_encoder pin_a)
# GPIO2 Handwheel B -> handwheel (sensor rotary_encoder pin_b)
# GPIO4 Axis encoder A -> axis_encoder (sensor rotary_encoder pin_a)
# GPIO5 Axis encoder B -> axis_encoder (sensor rotary_encoder pin_b)
# GPIO6 Axis encoder push -> axis_button (binary_sensor gpio) (inverted)
# GPIO7 Step encoder A -> step_encoder (sensor rotary_encoder pin_a)
# GPIO8 Step encoder B -> step_encoder (sensor rotary_encoder pin_b)
# GPIO9 Step encoder push -> step_button (binary_sensor gpio) (inverted)
# GPIO10 BT1 -> bt1 (binary_sensor gpio) (inverted)
# GPIO11 BT2 -> bt2 (binary_sensor gpio) (inverted)
# GPIO12 BT3 -> bt3 (binary_sensor gpio) (inverted)
# GPIO13 LCD E (SCK) -> spi (spi clk_pin)
# GPIO14 LCD R/W (MOSI) -> spi (spi mosi_pin)
# GPIO15 LCD RS (CS) -> lcd (display st7920 cs_pin)
# GPIO21 RGB LED -> status_rgb (light esp32_rmt_led_strip)
# GPIO39-44 free (BT4-BT6 later)
# LCD RST: RC to 3.3 V, PSB to GND (serial mode)
substitutions:
device: cnc-pendant
name: CNC Pendant
area: Workshop
comment: Klipper CNC pendant
moonraker: http://klipper.local:7125
max_feed: "3000" # mm/min, handwheel jog feed cap
esphome:
name: mcu-${device}
friendly_name: ${name}
area: ${area}
comment: ${comment}
includes:
- include/moonraker.h
on_boot:
- lambda: 'moonraker::client.start("${moonraker}");'
esp32:
variant: esp32s3
flash_size: 8MB
toolchain: esp-idf
framework:
type: esp-idf
packages:
common: !include common/common.yaml
# ipv6_only: !include common/ipv6_only.yaml
status_led: !include
file: common/status_led.yaml
vars:
light_id: status_rgb
light:
- platform: esp32_rmt_led_strip
id: status_rgb
name: LED
pin: 21
num_leds: 1
chipset: ws2812
rgb_order: GRB
restore_mode: ALWAYS_OFF
# only links esp_http_client for include/moonraker.h, which runs requests on its own task
http_request:
globals:
- id: axis
type: int
initial_value: "0" # 0 X, 1 Y, 2 Z
- id: step
type: int
initial_value: "1" # index into steps[] in the jog interval
- id: wheel_sent
type: float
initial_value: "0"
interval:
# handwheel: send the counts since the last jog as one relative move
- interval: 100ms
then:
- lambda: |-
static const float steps[] = {0.01f, 0.1f, 1.0f};
float delta = id(handwheel).state - id(wheel_sent);
if (delta == 0 || std::isnan(delta)) return;
id(wheel_sent) = id(handwheel).state;
float dist = delta * steps[id(step)];
// feed so the move takes ~100 ms, i.e. about one interval
// ponytail: capped feed lets fast spins queue moves that keep running after the wheel stops; drop excess counts if that bites
float feed = std::min(std::max(std::fabs(dist) * 600.0f, 60.0f), ${max_feed}.0f);
moonraker::client.gcode(str_sprintf("G91\nG1 %c%.3f F%.0f\nG90", "XYZ"[id(axis)], dist, feed));
sensor:
- platform: rotary_encoder
id: handwheel
pin_a:
number: 1
mode: INPUT_PULLUP
pin_b:
number: 2
mode: INPUT_PULLUP
resolution: 1 # calibration: counts per detent, flip pin_a/pin_b if direction is wrong
- platform: rotary_encoder
id: axis_encoder
pin_a:
number: 4
mode: INPUT_PULLUP
pin_b:
number: 5
mode: INPUT_PULLUP
on_clockwise:
- lambda: 'id(axis) = std::min(id(axis) + 1, 2);'
on_anticlockwise:
- lambda: 'id(axis) = std::max(id(axis) - 1, 0);'
- platform: rotary_encoder
id: step_encoder
pin_a:
number: 7
mode: INPUT_PULLUP
pin_b:
number: 8
mode: INPUT_PULLUP
on_clockwise:
- lambda: 'id(step) = std::min(id(step) + 1, 2);'
on_anticlockwise:
- lambda: 'id(step) = std::max(id(step) - 1, 0);'
binary_sensor:
- platform: gpio
id: stamp_button
name: Stamp Button
pin:
number: 0
inverted: true
# axis push: zero the selected axis in work coordinates
- platform: gpio
id: axis_button
name: Axis Button
pin:
number: 6
mode: INPUT_PULLUP
inverted: true
filters:
- delayed_on_off: 20ms
on_press:
- lambda: 'moonraker::client.gcode(str_sprintf("G92 %c0", "XYZ"[id(axis)]));'
- platform: gpio
id: step_button
name: Step Button
pin:
number: 9
mode: INPUT_PULLUP
inverted: true
filters:
- delayed_on_off: 20ms
# BT1: home all
- platform: gpio
id: bt1
name: BT1
pin:
number: 10
mode: INPUT_PULLUP
inverted: true
filters:
- delayed_on_off: 20ms
on_press:
- lambda: 'moonraker::client.gcode("G28");'
# BT2: pause / resume
- platform: gpio
id: bt2
name: BT2
pin:
number: 11
mode: INPUT_PULLUP
inverted: true
filters:
- delayed_on_off: 20ms
on_press:
- lambda: 'moonraker::client.post(moonraker::client.status().state == "paused" ? "/printer/print/resume" : "/printer/print/pause");'
# BT3: hold 1 s for emergency stop (Klipper needs FIRMWARE_RESTART afterwards)
- platform: gpio
id: bt3
name: BT3
pin:
number: 12
mode: INPUT_PULLUP
inverted: true
filters:
- delayed_on_off: 20ms
on_multi_click:
- timing:
- ON for at least 1s
then:
- lambda: 'moonraker::client.post("/printer/emergency_stop", "", true);'
font:
# X11 misc-fixed bitmap fonts (as in u8g2 / Marlin), 6 px wide: axis letter + "-123.456" fits 64 px
- file: assets/fonts/6x13.bdf
id: font_big
- file: assets/fonts/6x10.bdf
id: font_small
spi:
clk_pin: 13
mosi_pin: 14
display:
- platform: st7920
id: lcd
cs_pin:
number: 15
inverted: true # ST7920 RS/CS is active high
data_rate: 1MHz # default 200kHz takes ~220 ms per frame; drop back if the picture garbles
width: 128
height: 64
rotation: 90 # mounted portrait, 270 if upside down
update_interval: 200ms
lambda: |-
static const char *steps[] = {"0.01", "0.1", "1"};
auto s = moonraker::client.status();
it.printf(0, 0, id(font_small), "%s", s.state.c_str());
it.printf(0, 10, id(font_small), "H:%s", s.homed.empty() ? "-" : s.homed.c_str());
for (int i = 0; i < 3; i++) {
int y = 22 + i * 14;
Color c = COLOR_ON;
if (i == id(axis)) {
it.filled_rectangle(0, y, 64, 13);
c = COLOR_OFF;
}
it.printf(1, y + 1, id(font_big), c, "%c", "XYZ"[i]);
it.printf(63, y + 1, id(font_big), c, TextAlign::TOP_RIGHT, "%.3f", s.pos[i]);
}
it.printf(0, 118, id(font_small), "%s mm", steps[id(step)]);
+2
View File
@@ -22,6 +22,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
+2
View File
@@ -37,6 +37,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
+9 -9
View File
@@ -5,7 +5,7 @@
# GPIO22 -> speaker_id (speaker i2s_audio i2s_dout_pin)
# GPIO23 -> echo_microphone (microphone i2s_audio i2s_din_pin)
# GPIO26 Grove SDA
# GPIO27 -> LED (light esp32_rmt_led_strip)
# GPIO27 ATOM RGB LED -> LED [neo_buildin] (light esp32_rmt_led_strip), also status
# GPIO32 Grove SCL
# GPIO33 -> speaker_bus (i2s_audio i2s_lrclk_pin)
# GPIO39 -> Button (binary_sensor gpio) (inverted)
@@ -25,17 +25,17 @@ esphome:
esp32:
variant: esp32
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
external_components:
# speaker media player: skip a failed playlist item (esphome#19862), drop once merged
- source: github://randybb/esphome-components
components: [speaker]
refresh: 1h
status_led: !include
file: common/status_led.yaml
vars:
light_id: neo_buildin
api:
actions:
@@ -148,10 +148,10 @@ media_player:
buffer_size: 14000
media_pipeline:
speaker: media_spk_resampling_input
format: NONE
format: WAV # no PSRAM: HA transcodes to WAV, decoding MP3/FLAC here runs the heap out
announcement_pipeline:
speaker: announcement_spk_resampling_input
format: NONE
format: WAV # no PSRAM: HA transcodes to WAV, decoding MP3/FLAC here runs the heap out
rtttl:
id: my_rtttl
+2 -6
View File
@@ -28,6 +28,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
@@ -38,12 +40,6 @@ packages:
vars:
light_id: led_light
external_components:
# speaker media player: skip a failed playlist item (esphome#19862), drop once merged
- source: github://randybb/esphome-components
components: [speaker]
refresh: 1h
api:
actions:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
+12 -49
View File
@@ -10,7 +10,7 @@
# GPIO23 RS485 Tx
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
# GPIO26 I2C0 SDA - white
# GPIO27 NEO 1x
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL
# GPIO33 RS485 Rx
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
@@ -33,57 +33,30 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
external_components:
# - source: github://pr#12717
# components: [ds248x]
# refresh: 1h
- source: github://pr#13534
components: [ds2482, ds2484, ds248x_base]
refresh: 1h
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
i2c:
# - id: i2c0
# sda: 26
# scl: 32
# scan: true #false
# - id: i2c1
sda: 25
scl: 21
scan: true #false
# ds248x:
# # i2c_id: i2c_main
# address: 0x18 # should be the default
# # sleep_pin: 32 # remove if not needed, if set the ds248x sleeps when no transaction is in progress
# active_pullup: true # adds a active pullup which should improve signal integrity
# strong_pullup: false # enables a strong pullup used to provide the needed current for temperature reading without vcc connected
# bus_sleep: true # power down the bus when no transaction is in progres
# one_wire:
# id: one_wire_bus
# platform: ds2484
# active_pullup: true
# ds248x:
# id: ds2484_module
# address: 0x18
# one_wire:
# - platform: ds248x
# ds248x_id: ds2484_module
# id: one_wire_bus
ds248x:
id: ds2484_module
type: ds2482-100
address: 0x18
active_pullup: true
one_wire:
id: one_wire_bus
platform: ds2482
active_pullup: true
- platform: ds248x
ds248x_id: ds2484_module
id: one_wire_bus
pca9554:
- id: pca9554_module
@@ -130,16 +103,6 @@ sensor:
# index: 0
name: Temperature
id: 'heating_fireplace_temperature'
# - platform: dht
# pin: 14
# temperature:
# name: "Kitchen Temperature"
# id: 'kitchen_temperature'
# humidity:
# name: "Kitchen Humidity"
# id: 'kitchen_humidity'
# update_interval: 60s
# model: si7021
bluetooth_proxy:
active: true
+4 -1
View File
@@ -10,7 +10,7 @@
# GPIO23 RS485 TX
# GPIO25 I2C1 SDA red
# GPIO26 I2C0 SDA white
# GPIO27 NEO
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL -> gate_ogi_state (binary_sensor gpio) (inverted); gate_ogi_blink (binary_sensor gpio) (inverted)
# GPIO33 RS485 RX
# GPIO39 BUTTON
@@ -30,11 +30,14 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
button:
- platform: output
+2
View File
@@ -44,6 +44,7 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: generic
minimum_chip_revision: 3.0
sram1_as_iram: true
@@ -59,6 +60,7 @@ external_components:
packages:
# common: !include common/common.yaml
common_eth: !include common/common_eth.yaml
ipv6_only: !include common/ipv6_only_eth.yaml
i2c:
sda: 13
+13 -39
View File
@@ -10,7 +10,7 @@
# GPIO23 UART1 RX -> uart_modbus (uart rx_pin)
# GPIO25 I2C1 SDA -> i2c (i2c sda)
# GPIO26 I2C0 SDA
# GPIO27 NEO
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL
# GPIO33 UART1 TX -> uart_modbus (uart tx_pin)
# GPIO39 BUTTON
@@ -43,26 +43,14 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
external_components:
# - source: github://pr#12717
# components: [ds248x]
# refresh: 1h
- source: github://pr#13534
components: [ds2482, ds2484, ds248x_base]
refresh: 1h
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
#logger:
# level: VERBOSE
# logs:
# dallas.component: ERROR
# uart.component: ERROR
# i2c.component: VERBOSE
status_led: !include common/status_led_atom.yaml
# Heating / Hot water Controller
# temp_1: Solar Collector
@@ -167,36 +155,22 @@ climate:
default_target_temperature_high: 40 °C
i2c:
# - id: i2c0
# sda: 26
# scl: 32
# scan: true #false
# - id: i2c1
sda: 25
scl: 21
scan: true #false
# one_wire:
# id: one_wire_bus
# # i2c_id: i2c_main
# platform: ds2484
# active_pullup: true
# ds248x:
# id: ds2484_module
# address: 0x18
# active_pullup: true
# one_wire:
# - platform: ds248x
# ds248x_id: ds2484_module
# id: one_wire_bus
ds248x:
id: ds2482_module
type: ds2482-100
address: 0x18
active_pullup: true
one_wire:
id: one_wire_bus
# i2c_id: i2c_main
platform: ds2482
active_pullup: true
- platform: ds248x
ds248x_id: ds2482_module
id: one_wire_bus
modbus:
uart_id: uart_modbus
+6 -3
View File
@@ -10,7 +10,7 @@
# GPIO23 RS485 Tx
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
# GPIO26 I2C0 SDA - white
# GPIO27 NEO 1x
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL
# GPIO33 RS485 Rx
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
@@ -49,14 +49,17 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
api:
reboot_timeout: 300s
# api:
# reboot_timeout: 300s
i2c:
# - id: i2c0
+2
View File
@@ -26,6 +26,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
type: esp-idf
packages:
+2
View File
@@ -66,6 +66,8 @@ esp32:
variant: esp32s3
flash_size: 16MB
framework:
advanced:
flash_chip: boya
type: esp-idf
# PSRAM bandwidth for the RGB panel (not set by ESPHome); without it the
# image shifts during flash/WiFi activity
+2
View File
@@ -29,6 +29,8 @@ esp32:
flash_size: 16MB
toolchain: esp-idf
framework:
advanced:
flash_chip: generic # same board as lvgl-trainer (not read from the device)
type: esp-idf
packages:
+2
View File
@@ -37,6 +37,8 @@ esp32:
variant: esp32s3
flash_size: 16MB
framework:
advanced:
flash_chip: generic
type: esp-idf
packages:
+2
View File
@@ -104,6 +104,8 @@ esp32:
flash_size: 16MB
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
# PSRAM bandwidth for the RGB panel (not set by ESPHome); without it the
# image shifts during flash/WiFi activity
+4 -1
View File
@@ -10,7 +10,7 @@
# GPIO23 UART1 RX
# GPIO25 I2C1 SDA
# GPIO26 I2C0 SDA -> uart_modbus (uart rx_pin)
# GPIO27 NEO
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL -> uart_modbus (uart tx_pin)
# GPIO33 UART1 TX
# GPIO39 BUTTON
@@ -37,11 +37,14 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
modbus:
uart_id: uart_modbus
+185
View File
@@ -0,0 +1,185 @@
---
# Hardware: Nordic nRF52840 DK
# Pinout:
# P0.06 UART0 TX -> logger (J-Link VCOM)
# P0.13 LED 1 (active low) -> ANT+ Connected (a configured device is received)
# P0.14 LED 2 (active low) -> ANT+ Unknown Device (an unconfigured one is in range)
# P1.01 UART1 RX <- mcu-nrf-dk UART1 TX (P1.02), packet_transport
# P1.02 UART1 TX -> mcu-nrf-dk UART1 RX (P1.01), packet_transport; plus GND
# Radio: ANT+ receiver (RadiANT), no network of its own; values go to mcu-nrf-dk
# ANT+ devices:
# 655730 Garmin HRM-Pro heart rate
# 498521 Concept2 PM5 (rower) fitness equipment (FE-C)
# 1044953 Garmin Tempe environment (temperature)
# 604693 Garmin Varia RTL515 bike radar, battery only
# 136052 Garmin HRM-Dual heart rate (pain cave)
# 334424 Garmin HRM-Tri heart rate (bike)
# 886796 Garmin Rally RS200 power + cadence
# 343922 Garmin Speed Sensor 2 speed
# 42898 SRAM Force AXS shifting (Cube Litening C:68X), battery only
esphome:
name: mcu-nrf-ant
friendly_name: nRF ANT+
# needs the esphomeplatformzephyr fork (esphome-zephyr); RadiANT needs NCS
zephyr:
variant: NRF52
board: nrf52840dk/nrf52840
framework:
type: ncs
logger:
hardware_uart: UART0
external_components:
- source: github://randybb/esphome-components
components: [ant_plus]
output:
- platform: gpio
id: led_known
pin: {number: P0.13, inverted: true}
- platform: gpio
id: led_unknown
pin: {number: P0.14, inverted: true}
ant_plus:
network_key: !secret ant_plus_network_key
connected:
id: ant_connected
name: ANT+ Connected
on_press: {output.turn_on: led_known}
on_release: {output.turn_off: led_known}
unknown_device:
id: ant_unknown_device
name: ANT+ Unknown Device
on_press: {output.turn_on: led_unknown}
on_release: {output.turn_off: led_unknown}
devices:
- type: heart_rate # Garmin HRM-Pro
device_number: 655730
heart_rate:
id: hrm_pro_heart_rate
name: Garmin HRM-Pro Heart Rate
battery_level:
id: hrm_pro_battery
name: Garmin HRM-Pro Battery
- type: fitness_equipment # Concept2 PM5 (rower)
device_number: 498521
power:
id: pm5_power
name: Concept2 PM5 Power
cadence:
id: pm5_stroke_rate
name: Concept2 PM5 Stroke Rate
in_use:
id: pm5_in_use
name: Concept2 PM5 In Use
- type: temperature # Garmin Tempe
device_number: 1044953
temperature:
id: tempe_temperature
name: Garmin Tempe Temperature
temperature_min:
id: tempe_temperature_min
name: Garmin Tempe Temperature 24h Min
temperature_max:
id: tempe_temperature_max
name: Garmin Tempe Temperature 24h Max
battery_voltage:
id: tempe_battery
name: Garmin Tempe Battery
battery_low:
id: tempe_battery_low
name: Garmin Tempe Battery Low
- type: bike_radar # Garmin Varia RTL515
device_number: 604693
battery_voltage:
id: varia_battery
name: Garmin Varia RTL515 Battery
battery_low:
id: varia_battery_low
name: Garmin Varia RTL515 Battery Low
- type: heart_rate # Garmin HRM-Dual
device_number: 136052
heart_rate:
id: hrm_dual_heart_rate
name: Garmin HRM-Dual Heart Rate
battery_level:
id: hrm_dual_battery
name: Garmin HRM-Dual Battery
- type: heart_rate # Garmin HRM-Tri
device_number: 334424
heart_rate:
id: hrm_tri_heart_rate
name: Garmin HRM-Tri Heart Rate
battery_level:
id: hrm_tri_battery
name: Garmin HRM-Tri Battery
- type: power # Garmin Rally RS200 (a battery in each pedal)
device_number: 886796
power:
id: rally_power
name: Garmin Rally RS200 Power
cadence:
id: rally_cadence
name: Garmin Rally RS200 Cadence
battery_low:
id: rally_battery_low
name: Garmin Rally RS200 Battery Low
- type: speed # Garmin Speed Sensor 2
device_number: 343922
speed:
id: speed2_speed
name: Garmin Speed Sensor 2 Speed
battery_voltage:
id: speed2_battery
name: Garmin Speed Sensor 2 Battery
battery_low:
id: speed2_battery_low
name: Garmin Speed Sensor 2 Battery Low
- type: shifting # SRAM Force AXS (Cube Litening C:68X)
device_number: 42898
battery_low:
id: sram_battery_low
name: SRAM Force AXS Battery Low
uart:
id: link
port: UART1
# the DK's default UART1 pins, same on both boards, wires crossed
tx_pin: P1.02
rx_pin: P1.01
baud_rate: 115200
packet_transport:
- platform: uart
uart_id: link
update_interval: 1s
sensors:
- hrm_pro_heart_rate
- hrm_pro_battery
- pm5_power
- pm5_stroke_rate
- tempe_temperature
- tempe_temperature_min
- tempe_temperature_max
- tempe_battery
- varia_battery
- hrm_dual_heart_rate
- hrm_dual_battery
- hrm_tri_heart_rate
- hrm_tri_battery
- rally_power
- rally_cadence
- speed2_speed
- speed2_battery
binary_sensors:
- ant_connected
- ant_unknown_device
- pm5_in_use
- tempe_battery_low
- varia_battery_low
- rally_battery_low
- speed2_battery_low
- sram_battery_low
+289 -5
View File
@@ -1,12 +1,296 @@
---
# Hardware: Nordic nRF52840 DK
# Pinout:
# P0.11 Button 1 (active low) -> Button 1 (binary_sensor gpio)
# P0.12 Button 2 (active low) -> Button 2 (binary_sensor gpio)
# P0.13 LED 1 (active low) -> LED 1 (light binary)
# P0.14 LED 2 (active low) -> LED 2 (light binary)
# P0.15 LED 3 (active low) -> LED 3 (light binary)
# P0.16 LED 4 (active low) -> LED 4 (light binary)
# P0.24 Button 3 (active low) -> Button 3 (binary_sensor gpio)
# P0.25 Button 4 (active low) -> Button 4 (binary_sensor gpio)
# P1.01 UART1 RX <- mcu-nrf-ant UART1 TX (P1.02), packet_transport; plus GND
# P1.02 UART1 TX -> mcu-nrf-ant UART1 RX (P1.01), packet_transport
# ANT+ values (Garmin HRM-Pro, Concept2 PM5, Garmin Tempe, Garmin Varia RTL515) come from mcu-nrf-ant
esphome:
name: mcu-nrf-dk
friendly_name: mcu-nrf-dk
friendly_name: nRF DK
nrf52:
board: nrf52840_dk
bootloader: adafruit_nrf52_sd140_v7
# needs the esphomeplatformzephyr fork (esphome-zephyr), upstream has no zephyr: platform yet
zephyr:
variant: NRF52
board: nrf52840dk/nrf52840
framework:
type: zephyr
# Enable logging
logger:
network:
enable_ipv6: true
# Active dataset of the Thread network (HA: Settings > Thread > ... > dataset TLV)
openthread:
tlv: !secret thread_tlv
# end device, doesn't route for others; saves flash (FTD fills the MCUboot slot)
device_type: MTD
api:
encryption:
key: !secret api_key
# ANT+ values from mcu-nrf-ant (second nRF52840 DK) over UART
uart:
id: ant_link
port: UART1
# the DK's default UART1 pins, same on both boards, wires crossed
rx_pin: P1.01
tx_pin: P1.02
baud_rate: 115200
packet_transport:
- platform: uart
uart_id: ant_link
providers:
- name: mcu-nrf-ant
sensor:
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_pro_heart_rate
name: Garmin HRM-Pro Heart Rate
internal: false
unit_of_measurement: bpm
icon: mdi:heart-pulse
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_pro_battery
name: Garmin HRM-Pro Battery
internal: false
unit_of_measurement: "%"
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: pm5_power
name: Concept2 PM5 Power
internal: false
unit_of_measurement: W
device_class: power
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: pm5_stroke_rate
name: Concept2 PM5 Stroke Rate
internal: false
unit_of_measurement: spm
icon: mdi:rowing
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: tempe_temperature
name: Garmin Tempe Temperature
internal: false
unit_of_measurement: °C
device_class: temperature
accuracy_decimals: 1
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: tempe_temperature_min
name: Garmin Tempe Temperature 24h Min
internal: false
unit_of_measurement: °C
device_class: temperature
accuracy_decimals: 1
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: tempe_temperature_max
name: Garmin Tempe Temperature 24h Max
internal: false
unit_of_measurement: °C
device_class: temperature
accuracy_decimals: 1
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: tempe_battery
name: Garmin Tempe Battery
internal: false
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 2
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: varia_battery
name: Garmin Varia RTL515 Battery
internal: false
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 2
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_dual_heart_rate
name: Garmin HRM-Dual Heart Rate
internal: false
unit_of_measurement: bpm
icon: mdi:heart-pulse
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_dual_battery
name: Garmin HRM-Dual Battery
internal: false
unit_of_measurement: "%"
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_tri_heart_rate
name: Garmin HRM-Tri Heart Rate
internal: false
unit_of_measurement: bpm
icon: mdi:heart-pulse
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: hrm_tri_battery
name: Garmin HRM-Tri Battery
internal: false
unit_of_measurement: "%"
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: rally_power
name: Garmin Rally RS200 Power
internal: false
unit_of_measurement: W
device_class: power
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: rally_cadence
name: Garmin Rally RS200 Cadence
internal: false
unit_of_measurement: rpm
icon: mdi:rotate-right
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: speed2_speed
name: Garmin Speed Sensor 2 Speed
internal: false
unit_of_measurement: m/s
device_class: speed
accuracy_decimals: 2
filters:
- throttle: 1s
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: speed2_battery
name: Garmin Speed Sensor 2 Battery
internal: false
unit_of_measurement: V
device_class: voltage
accuracy_decimals: 2
entity_category: diagnostic
output:
- platform: gpio
id: led_1_out
pin: {number: P0.13, inverted: true}
- platform: gpio
id: led_2_out
pin: {number: P0.14, inverted: true}
- platform: gpio
id: led_3_out
pin: {number: P0.15, inverted: true}
- platform: gpio
id: led_4_out
pin: {number: P0.16, inverted: true}
light:
- {platform: binary, name: LED 1, id: led_1, output: led_1_out}
- {platform: binary, name: LED 2, id: led_2, output: led_2_out}
- {platform: binary, name: LED 3, id: led_3, output: led_3_out}
- {platform: binary, name: LED 4, id: led_4, output: led_4_out}
# each button toggles its LED locally and is visible in HA
binary_sensor:
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: ant_connected
name: ANT+ Connected
internal: false
device_class: connectivity
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: ant_unknown_device
name: ANT+ Unknown Device
internal: false
icon: mdi:access-point
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: pm5_in_use
name: Concept2 PM5 In Use
internal: false
device_class: running
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: tempe_battery_low
name: Garmin Tempe Battery Low
internal: false
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: varia_battery_low
name: Garmin Varia RTL515 Battery Low
internal: false
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: rally_battery_low
name: Garmin Rally RS200 Battery Low
internal: false
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: speed2_battery_low
name: Garmin Speed Sensor 2 Battery Low
internal: false
device_class: battery
entity_category: diagnostic
- platform: packet_transport
provider: mcu-nrf-ant
remote_id: sram_battery_low
name: SRAM Force AXS Battery Low
internal: false
device_class: battery
entity_category: diagnostic
- platform: gpio
name: Button 1
pin: {number: P0.11, inverted: true, mode: {input: true, pullup: true}}
on_press: {light.toggle: led_1}
- platform: gpio
name: Button 2
pin: {number: P0.12, inverted: true, mode: {input: true, pullup: true}}
on_press: {light.toggle: led_2}
- platform: gpio
name: Button 3
pin: {number: P0.24, inverted: true, mode: {input: true, pullup: true}}
on_press: {light.toggle: led_3}
- platform: gpio
name: Button 4
pin: {number: P0.25, inverted: true, mode: {input: true, pullup: true}}
on_press: {light.toggle: led_4}
+1
View File
@@ -28,6 +28,7 @@ esphome:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
nspanel: !include
file: common/nspanel.yaml
vars:
+1
View File
@@ -51,6 +51,7 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: generic
minimum_chip_revision: 3.0
sram1_as_iram: true
+1
View File
@@ -27,6 +27,7 @@ esphome:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
nspanel: !include
file: common/nspanel.yaml
vars:
+1
View File
@@ -27,6 +27,7 @@ esphome:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
nspanel: !include
file: common/nspanel.yaml
vars:
+1
View File
@@ -27,6 +27,7 @@ esphome:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
nspanel: !include
file: common/nspanel.yaml
vars:
+2
View File
@@ -29,6 +29,8 @@ esp32:
variant: esp32c3
toolchain: esp-idf
framework:
advanced:
flash_chip: generic
type: esp-idf
packages:
+4 -1
View File
@@ -10,7 +10,7 @@
# GPIO23 RS485 Tx
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
# GPIO26 I2C0 SDA - white
# GPIO27 NEO 1x
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 I2C0 SCL
# GPIO33 RS485 Rx
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
@@ -50,11 +50,14 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
i2c:
+1 -1
View File
@@ -30,6 +30,7 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: gd
minimum_chip_revision: 3.1
sram1_as_iram: true
@@ -199,4 +200,3 @@ switch:
- delay: 500ms
- switch.turn_off: relay_off # bi-stable relay so no need to keep on
interlock: [relay_on]
+1
View File
@@ -30,6 +30,7 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: gd # same device as pow-dishwasher (not read from the device)
minimum_chip_revision: 3.1
sram1_as_iram: true
+4
View File
@@ -7,6 +7,7 @@
# GPIO23 -> spi (spi clk_pin)
# GPIO25 -> rf_rx (remote_receiver)
# GPIO26 Grove SDA
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 Grove SCL
# GPIO33 -> cc1101 (cc1101 cs_pin)
substitutions:
@@ -25,11 +26,14 @@ esp32:
variant: esp32
flash_size: 4MB
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
spi:
clk_pin: 23
+1
View File
@@ -21,6 +21,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
remote_receiver:
pin: 4
+285
View File
@@ -0,0 +1,285 @@
---
# Hardware: M5Stack M5Stamp S3 + PN5180 module (5 V and 3.3 V both needed)
# Pinout:
# GPIO0 Button
# GPIO3 (external RFID LED, not fitted yet; notify_led uses the onboard RGB for now)
# GPIO4 Buzzer -> buzzer (output ledc)
# GPIO5 -> spi (spi miso_pin) PN5180 MISO
# GPIO6 -> spi (spi mosi_pin) PN5180 MOSI
# GPIO7 -> spi (spi clk_pin) PN5180 SCK
# GPIO8 -> pn5180 (cs_pin) PN5180 NSS
# GPIO9 -> pn5180 (busy_pin) PN5180 BUSY
# GPIO10 -> pn5180 (reset_pin) PN5180 RST
# GPIO11 -> pn5180 (irq_pin) PN5180 IRQ
# GPIO19 U-
# GPIO20 U+
# GPIO21 RGB -> notify_led (light esp32_rmt_led_strip), also status_led
# PN5180 REQ, AUX, GPIO left open (REQ high at reset = firmware download mode)
substitutions:
device: rfid-openprinttag
name: OpenPrintTag
area: DEV
comment: Filament spool reader (OpenPrintTag, Creality CFS)
esphome:
name: mcu-${device}
friendly_name: ${name}
area: ${area}
comment: ${comment}
esp32:
variant: esp32s3
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include
file: common/status_led.yaml
vars:
light_id: notify_led
show_errors: "true"
external_components:
- source: github://randybb/esphome-components
components: [pn5180, openprinttag, creality_cfs]
refresh: 1h
# Called by the OpenPrintTag integration (openprinttag.update) to update the aux region
api:
actions:
- action: openprinttag_write_aux
variables:
uid: string
aux: string
then:
- if:
condition:
switch.is_on: led_enabled
then:
- light.turn_on:
id: notify_led
brightness: 100%
red: 100%
green: 0%
blue: 0%
flash_length: 500ms
- lambda: id(spool).write_aux(uid, aux);
# Writes a Creality CFS record (48 characters, optionally 48 more for sector 2) to the
# Creality tag on the reader
- action: creality_cfs_write
variables:
uid: string
data: string
then:
- if:
condition:
switch.is_on: led_enabled
then:
- light.turn_on:
id: notify_led
brightness: 100%
red: 100%
green: 0%
blue: 0%
flash_length: 500ms
- lambda: id(creality).write(uid, data);
spi:
clk_pin: GPIO7
mosi_pin: GPIO6
miso_pin: GPIO5
pn5180:
id: pn5180_reader
cs_pin: GPIO8
busy_pin: GPIO9
reset_pin: GPIO10
irq_pin: GPIO11
on_tag:
- if:
condition:
switch.is_on: led_enabled
then:
- light.turn_on:
id: notify_led
brightness: 100%
red: 0%
green: 100%
blue: 0%
flash_length: 500ms
- if:
condition:
switch.is_on: buzzer_enabled
then:
- rtttl.play: "success:d=32,o=5,b=100:c,g,b"
- homeassistant.tag_scanned: !lambda return x;
on_tag_removed:
- if:
condition:
switch.is_on: buzzer_enabled
then:
- rtttl.play: "removed:d=16,o=5,b=100:b"
openprinttag:
id: spool
# Raw tag record for the OpenPrintTag integration (randybb/ha-openprinttag), empty when removed
on_openprinttag:
- homeassistant.event:
event: esphome.openprinttag
data:
uid: !lambda return uid;
payload: !lambda return payload;
creality_cfs:
id: creality
# The Creality record (ASCII) for Home Assistant, empty when removed
on_creality:
- homeassistant.event:
event: esphome.creality_cfs
data:
uid: !lambda return uid;
data: !lambda return data;
sensor:
- platform: creality_cfs
name: Creality length
- platform: openprinttag
type: remaining_weight
name: Remaining weight
- platform: openprinttag
type: consumed_weight
name: Consumed weight
- platform: openprinttag
type: actual_weight
name: Full weight
- platform: openprinttag
type: min_print_temperature
name: Min print temperature
- platform: openprinttag
type: max_print_temperature
name: Max print temperature
- platform: openprinttag
type: max_bed_temperature
name: Max bed temperature
- platform: openprinttag
type: drying_temperature
name: Drying temperature
- platform: openprinttag
type: drying_time
name: Drying time
text_sensor:
- platform: pn5180
name: Tag UID
- platform: creality_cfs
type: material_id
name: Creality material ID
- platform: creality_cfs
type: color
name: Creality color
id: creality_color
on_value:
- script.execute: show_filament_color
- platform: creality_cfs
type: serial
name: Creality serial
- platform: openprinttag
type: material_type
name: Material
- platform: openprinttag
type: material_name
name: Material name
- platform: openprinttag
type: brand_name
name: Brand
- platform: openprinttag
type: primary_color
name: Color
id: openprinttag_color
on_value:
- script.execute: show_filament_color
script:
# The filament color on the filament_color light: the OpenPrintTag's, else the Creality tag's
- id: show_filament_color
then:
- lambda: |-
std::string x = id(openprinttag_color).state;
if (x.size() < 7)
x = id(creality_color).state;
if (x.size() < 7) {
id(filament_color).turn_off().set_transition_length(0).perform();
return;
}
uint32_t c = strtoul(x.c_str() + 1, nullptr, 16);
if (x.size() > 7)
c >>= 8; // #rrggbbaa
// ESPHome scales the strongest channel to 100 %, the darkness goes to the brightness
const float r = ((c >> 16) & 0xFF) / 255.0f, g = ((c >> 8) & 0xFF) / 255.0f, b = (c & 0xFF) / 255.0f;
const float m = std::max({r, g, b});
if (m == 0.0f) {
id(filament_color).turn_off().set_transition_length(0).perform(); // black
return;
}
id(filament_color).turn_on()
.set_rgb(r, g, b)
.set_brightness(m)
.set_transition_length(0)
.perform();
light:
# Onboard RGB for now: tag feedback and status. With the external LED fitted, move
# notify_led to pin 3 and give the onboard one back to status_led (as on mcu-rfid-reader)
- platform: esp32_rmt_led_strip
id: notify_led
name: Notify LED
channel_colors: GRB
pin: 21
num_leds: 1
chipset: ws2812
restore_mode: ALWAYS_OFF
rmt_symbols: 96
# Shows the filament color in Home Assistant; drives nothing, the next tag read overwrites it
- platform: rgb
id: filament_color
name: Filament color
icon: mdi:printer-3d-nozzle
red: color_none
green: color_none
blue: color_none
restore_mode: ALWAYS_OFF
default_transition_length: 0s
output:
- platform: ledc
pin: 4
id: buzzer
- platform: template
id: color_none
type: float
write_action: []
rtttl:
output: buzzer
switch:
- platform: template
name: Buzzer Enabled
id: buzzer_enabled
icon: mdi:volume-high
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
- platform: template
name: LED enabled
id: led_enabled
icon: mdi:alarm-light-outline
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
+14 -12
View File
@@ -28,7 +28,7 @@ esphome:
# - wait_until:
# api.connected:
# - logger.log: API is connected!
# - rtttl.play: "success:d=24,o=5,b=100:c,g,b"
# - rtttl.play: "success:d=32,o=5,b=100:c,g,b"
# - light.turn_on:
# id: notify_led
# brightness: 100%
@@ -43,6 +43,8 @@ esp32:
variant: esp32s3
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
# external_components:
@@ -89,13 +91,13 @@ api:
uri += tag_id;
message->add_uri_record(uri);
id(pn532_module).write_mode(message);
- rtttl.play: "write:d=24,o=5,b=100:b"
- rtttl.play: "write:d=32,o=5,b=100:b"
- wait_until:
not:
pn532.is_writing:
- light.turn_off:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- rtttl.play: "write:d=32,o=5,b=100:b,b"
- action: write_music_tag
variables:
@@ -121,13 +123,13 @@ api:
message->add_text_record(text);
}
id(pn532_module).write_mode(message);
- rtttl.play: "write:d=24,o=5,b=100:b"
- rtttl.play: "write:d=32,o=5,b=100:b"
- wait_until:
not:
pn532.is_writing:
- light.turn_off:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- rtttl.play: "write:d=32,o=5,b=100:b,b"
globals:
- id: source
@@ -169,7 +171,7 @@ pn532_i2c:
id(info)="";
if (tag.has_ndef_message()) {
auto message = tag.get_ndef_message();
auto records = message->get_records();
const auto &records = message->get_records();
for (auto &record : records) {
std::string payload = record->get_payload();
std::string type = record->get_type();
@@ -269,7 +271,7 @@ pn532_i2c:
condition:
switch.is_on: buzzer_enabled
then:
- rtttl.play: "success:d=24,o=5,b=100:c,g,b"
- rtttl.play: "success:d=32,o=5,b=100:c,g,b"
on_tag_removed:
then:
- homeassistant.event:
@@ -311,13 +313,13 @@ button:
message->add_uri_record(uri);
ESP_LOGD("tagreader", "Writing payload: %s", uri.c_str());
id(pn532_module).write_mode(message);
- rtttl.play: "write:d=24,o=5,b=100:b"
- rtttl.play: "write:d=32,o=5,b=100:b"
- wait_until:
not:
pn532.is_writing:
- light.turn_off:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- rtttl.play: "write:d=32,o=5,b=100:b,b"
- platform: template
name: Clean Tag
id: clean_tag
@@ -331,13 +333,13 @@ button:
green: 64.7%
blue: 0%
- lambda: 'id(pn532_module).clean_mode();'
- rtttl.play: "write:d=24,o=5,b=100:b"
- rtttl.play: "write:d=32,o=5,b=100:b"
- wait_until:
not:
pn532.is_writing:
- light.turn_off:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- rtttl.play: "write:d=32,o=5,b=100:b,b"
- platform: template
name: Cancel writing
id: cancel_writing
@@ -347,7 +349,7 @@ button:
- lambda: 'id(pn532_module).read_mode();'
- light.turn_off:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- rtttl.play: "write:d=32,o=5,b=100:b,b"
light:
- platform: esp32_rmt_led_strip
+4 -1
View File
@@ -6,6 +6,7 @@
# GPIO22 -> Garden Light (switch gpio)
# GPIO25 -> i2c (i2c sda)
# GPIO26 Grove SDA
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 Grove SCL
# I2C:
# 0x27 pca9554_module (pca9554)
@@ -25,6 +26,8 @@ esp32:
variant: esp32
toolchain: esp-idf
framework:
advanced:
flash_chip: gd
type: esp-idf
# version: 5.4.2
# platform_version: 54.03.21
@@ -32,6 +35,7 @@ esp32:
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
i2c:
sda: 25
@@ -119,4 +123,3 @@ switch:
pin:
number: 19
mode: OUTPUT
+1
View File
@@ -29,6 +29,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
binary_sensor:
- platform: gpio
+1
View File
@@ -29,6 +29,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
binary_sensor:
- platform: gpio
+2
View File
@@ -30,11 +30,13 @@ esphome:
friendly_name: ${name}
area: ${area}
comment: ${comment}
esp8266:
board: esp01_1m
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
binary_sensor:
- platform: gpio
+4 -1
View File
@@ -63,8 +63,11 @@ esphome:
esp32:
variant: esp32s3
flash_size: 16MB
flash_frequency: 40MHz # the IDF 5.5.5 bootloader reads garbage from this flash (mfr 0x46) at 80MHz
toolchain: esp-idf
framework:
advanced:
flash_chip: generic
type: esp-idf
psram:
@@ -80,7 +83,7 @@ external_components:
components: [axp2101, aw88298, aw9523b, si12t, m5ioe1, ftservo, scs9009]
refresh: 0s
- source: github://randybb/esphome-components
components: [audio_spectrum, speaker] # speaker: esphome#19862, drop once merged
components: [audio_spectrum]
refresh: 1h
globals:
+13 -2
View File
@@ -20,6 +20,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
# wifi:
# use_address: mcu-mini-04.local
@@ -53,8 +54,18 @@ binary_sensor:
entity_id: binary_sensor.zigbee_staircase_pir_occupancy
on_state:
if:
condition:
binary_sensor.is_off: motion
condition: &no_motion
and:
- binary_sensor.is_off: motion
- binary_sensor.is_off: motion_2
then:
- light.turn_off: light_relay
- platform: homeassistant
id: motion_2
entity_id: binary_sensor.zigbee_staircase_2_pir_occupancy
on_state:
if:
condition: *no_motion
then:
- light.turn_off: light_relay
+2
View File
@@ -28,6 +28,8 @@ esphome:
esp32:
variant: esp32c3
framework:
advanced:
flash_chip: generic
type: esp-idf
packages:
+1
View File
@@ -34,6 +34,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
light:
- platform: status_led
+1
View File
@@ -23,6 +23,7 @@ esp8266:
packages:
common: !include common/common_esp8266.yaml
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
binary_sensor:
- platform: gpio
+3 -1
View File
@@ -5,6 +5,7 @@
# GPIO23 -> modbus_uart (uart tx_pin)
# GPIO25 -> i2c (i2c sda)
# GPIO26 Grove SDA
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
# GPIO32 Grove SCL
# GPIO33 -> modbus_uart (uart rx_pin)
# I2C:
@@ -40,11 +41,13 @@ esp32:
framework:
type: esp-idf
advanced:
flash_chip: gd
sram1_as_iram: true
packages:
common: !include common/common.yaml
ipv6_only: !include common/ipv6_only.yaml
status_led: !include common/status_led_atom.yaml
api:
actions:
@@ -368,4 +371,3 @@ valve:
- switch.turn_on: irrigation_relay_8
close_action:
- switch.turn_off: irrigation_relay_8
+6
View File
@@ -29,3 +29,9 @@ ble_beacon_toyota_auris_minor: 61958
ble_beacon_toyota_yaris_uuid: "00000000-0000-0000-0000-000000000000"
ble_beacon_toyota_yaris_honda_major: 10167
ble_beacon_toyota_yaris_honda_minor: 61958
# Thread active dataset (hex TLV) from Home Assistant
thread_tlv: "0E080000000000010000"
# ANT+ network key (8 bytes hex), from thisisant.com
ant_plus_network_key: "0000000000000000"