Skip to content

Instantly share code, notes, and snippets.

@JavanXD
Last active November 24, 2025 16:30
Show Gist options
  • Select an option

  • Save JavanXD/696d026ef202a7d6455ed4745df63e39 to your computer and use it in GitHub Desktop.

Select an option

Save JavanXD/696d026ef202a7d6455ed4745df63e39 to your computer and use it in GitHub Desktop.
ESPHome/Homeassistant - Sniff CAN-Bus (MCP2515) from LEDA LUC2
substitutions:
name: esphome-ledaluc2
friendly_name: ESPHome LEDA LUC2
esphome:
name: ${name}
friendly_name: ${friendly_name}
min_version: 2023.6.0 # Use a stable ESPHome version for compatibility
name_add_mac_suffix: false # Prevent adding MAC suffix to the device name
project:
name: esphome.web
version: dev # Version of the project
esp32:
board: esp32dev # Specify the ESP32 development board
framework:
type: arduino # Use the Arduino framework
# Enable logging for debugging purposes
logger:
# Enable Home Assistant API with encryption key from secrets.yaml
api:
encryption:
key: !secret api_key
# Enable over-the-air updates for firmware
ota:
platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Fallback hotspot in case Wi-Fi connection fails
ap:
ssid: "ESPHome-LEDALUC2"
password: !secret ap_password
# Allow Wi-Fi provisioning via serial connection
improv_serial:
# Enable captive portal for Wi-Fi provisioning via the fallback hotspot
captive_portal:
# Import specific components from an example configuration without overwriting local settings
dashboard_import:
package_import_url: github://esphome/example-configs/esphome-web/esp32.yaml@main
import_full_config: false
# Host a simple web server (e.g., for Improv Wi-Fi)
web_server:
# Configure the SPI interface for the MCP2515 CAN bus module
spi:
clk_pin: GPIO22 # Clock pin
miso_pin: GPIO17 # Master In Slave Out pin
mosi_pin: GPIO21 # Master Out Slave In pin
# Configure the CAN bus using the MCP2515 module
canbus:
- platform: mcp2515
cs_pin: GPIO16
can_id: 0x28A
bit_rate: 125KBPS
on_frame:
- can_id: 0x28A
then:
- lambda: |-
// Log all received CAN frames for debugging
if (x.size() > 0 && x.size() < 8) {
// Log the received frame data safely
std::string frame_data;
for (size_t i = 0; i < x.size(); i++) {
char byte_str[5];
snprintf(byte_str, sizeof(byte_str), "0x%02X ", x[i]);
frame_data += byte_str;
}
// Log the frame data in a single line
ESP_LOGD("CAN", "Received CAN Frame (Size: %d bytes): %s", x.size(), frame_data.c_str());
// Check for specific sizes and log states
if (x.size() == 2) {
ESP_LOGI("CAN", "Interpreted State: Ventilation turned OFF via Display");
} else if (x.size() == 1) {
ESP_LOGI("CAN", "Interpreted State: Ventilation turned ON via Display");
} else {
ESP_LOGW("CAN", "Interpreted State: Unknown or Additional Data");
}
}
else if (x.size() == 8) {
uint8_t frame_type = x[0]; // First byte determines the frame type
// Frame type 0x00: Pressure difference and exhaust temperature
if (frame_type == 0x00) {
// Extract pressure difference from Byte 2
float pressure_difference = x[1] * 0.1f; // Convert to Pascals
// Check for adjustment flag in Byte 3
if (x[2] == 0x81) {
const float PRESSURE_ADJUSTMENT_VALUE = 25.5f;
pressure_difference += PRESSURE_ADJUSTMENT_VALUE;
ESP_LOGI("CAN", "Adjustment Applied: +%.1f Pa", PRESSURE_ADJUSTMENT_VALUE);
}
// Extract exhaust temperature from Byte 4
uint16_t raw_temp = x[3] | (x[4] << 8); // Little Endian
float exhaust_temperature = static_cast<float>(raw_temp); // °C
// Log decoded values
ESP_LOGI("CAN", "Pressure: %.1f Pa, Temperature: %.1f °C", pressure_difference, exhaust_temperature);
// Publish to sensors
id(pressure_difference_sensor).publish_state(pressure_difference);
id(exhaust_temperature_sensor).publish_state(exhaust_temperature);
}
// Frame type 0x01: Ventilation status
else if (frame_type == 0x01) {
// Extract ventilation status from Byte 6
bool ventilation_active = (x[5] == 0x01);
// Log ventilation status
ESP_LOGI("CAN", "Ventilation Active: %s", ventilation_active ? "Yes" : "No");
ESP_LOGD("CAN", "Ventilation Bytes: Data=%02X %02X %02X %02X %02X %02X %02X %02X",
x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
// Publish to binary sensor
id(ventilation_status_sensor).publish_state(ventilation_active);
}
// Frame type 0x09: Heartbeat signal
else if (frame_type == 0x09) {
// Log loop and counter for reference
ESP_LOGD("CAN", "Heartbeat (0x09): Loop=%02X, Counter=%02X", x[2], x[1]);
}
// Frame type 0x55: Heartbeat signal
else if (frame_type == 0x55) {
// Log loop and counter for reference
ESP_LOGD("CAN", "Heartbeat (0x55): Loop=%02X, Counter=%02X", x[2], x[1]);
}
else if (frame_type == 0x80) {
ESP_LOGW("CAN", "Error Frame (0x80): Data=%02X %02X %02X %02X %02X %02X %02X %02X",
x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
}
else if (frame_type == 0x81) {
ESP_LOGW("CAN", "Error Frame (0x81): Data=%02X %02X %02X %02X %02X %02X %02X %02X",
x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
}
// Handle unknown frame types
else {
ESP_LOGW("CAN", "Unknown Frame Type. Data=%02X %02X %02X %02X %02X %02X %02X %02X",
x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
}
} else {
ESP_LOGW("CAN", "Unexpected frame size: %d bytes", x.size());
}
# Define template sensors to hold the values published from the CAN bus data
sensor:
- platform: template
name: "Pressure Difference"
id: pressure_difference_sensor
unit_of_measurement: "Pa"
accuracy_decimals: 1
device_class: pressure # Device class for pressure sensors
icon: "mdi:air-filter" # Optional custom icon for visual clarity
filters:
- throttle_average: 3s
- platform: template
name: "Exhaust Temperature"
id: exhaust_temperature_sensor
unit_of_measurement: "°C"
accuracy_decimals: 1
device_class: temperature # Device class for temperature sensors
icon: "mdi:thermometer"
filters:
- throttle_average: 3s
binary_sensor:
- platform: template
name: "Ventilation Status"
id: ventilation_status_sensor
device_class: running # Device class for indicating system activity
icon: "mdi:fan" # Optional custom icon for ventilation
@ChristophWeigert
Copy link

ChristophWeigert commented Nov 8, 2025

Könnt ihr nochmal Fotos machen wie was angelötet/verbunden ist? Ich bekomme es nicht hin Daten zu empfangen 😢

Hier Bilder wie es aktuell aussieht: https://immich.weigert.cc/s/ledalux2

Log:


Time | Level | Tag | Message
-- | -- | -- | --
18:10:17 | [I] | [safe_mode:042] | Boot seems successful; resetting boot loop counter
18:10:17 | [D] | [esp32.preferences:149] | Writing 1 items: 0 cached, 1 written, 0 failed
18:13:42 | [D] | [api:160] | Accept 192.168.1.108
18:13:42 | [D] | [api.connection:1383] | ESPHome Logs 2025.10.4 (192.168.1.108) connected
18:13:43 | [I] | [app:185] | ESPHome version 2025.10.4 compiled on Nov  8 2025, 17:05:29
18:13:43 | [I] | [app:187] | Project esphome.web version dev
18:13:43 | [C] | [wifi:679] | WiFi:
18:13:43 | [C] | [wifi:458] | Local MAC: 8C:4F:00:28:33:58
18:13:43 | [C] | [wifi:465] | IP Address: c0a8:647e:61c:403f:98f3:d80:80ec:fb3f
18:13:43 | [C] | [wifi:469] | SSID: �[5m'W-IoT'
18:13:43 | [C] | [logger:261] | Log
18:13:43 | [C] | [logger:267] | Log Baud Rate: 11
18:13:43 | [C] | [logger:274] | Task Log Buffer Size: 768
18:13:43 | [C] | [spi:067] | SPI bus:
18:13:43 | [C] | [spi:068] | CLK Pin: GPIO22
18:13:43 | [C] | [spi:069] | SDI Pin: GPIO17
18:13:43 | [C] | [spi:070] | SDO Pin: GPIO21
18:13:43 | [C] | [spi:075] | Using HW SPI: SPI
18:13:43 | [C] | [canbus:020] | config standard id=0x28a
18:13:43 | [E] | [component:154] | canbus is marked FAILED: unspecified
18:13:43 | [C] | [captive_portal:116] | Captive Portal:
18:13:43 | [C] | [web_server:317] | Web Ser
18:13:43 | [C] | [esphome.ota:093] | Over-The-Air upda
18:13:43 | [C] | [esphome.ota:100] | Password configured
18:13:43 | [C] | [safe_mode:018] | Safe M
18:13:43 | [C] | [web_server.ota:241] | Web Server OTA
18:13:43 | [C] | [api:222] | Ser
18:13:43 | [C] | [api:229] | Noise encryption: YES
18:13:43 | [C] | [improv_serial:031] | Improv Serial:
18:13:43 | [C] | [mdns:179] | m

@Maigus2510
Copy link

Hey, könnte mir einer von euch so ein Teio zusammenbauen und zuschicken? Bin selbst zu dumm dazu. Bezahlung natürlich nach eurem Preis ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment