Last active
February 2, 2026 14:25
-
-
Save JavanXD/696d026ef202a7d6455ed4745df63e39 to your computer and use it in GitHub Desktop.
ESPHome/Homeassistant - Sniff CAN-Bus (MCP2515) from LEDA LUC2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Author
Author
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
Hier sind Bilder: https://javan.de/hacking-the-fireplace/ Tatsächlich habe ich es gar nicht löten müssen, sondern ausschließlich gesteckt. Der MCP2515 hat passend übereingestimmt mit der Pin-Reihenfolge von meinem ESP32. Oben ist die Einkaufsliste mit den Links, die ich genutzt habe.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Schau mal, hier ist die Einkaufsliste: https://gist.github.com/JavanXD/696d026ef202a7d6455ed4745df63e39?permalink_comment_id=5297526#gistcomment-5297526 Du kannst dir die 5V aus den 12V Pins holen.