I try to create a external component for a DCF77 receiver for ESPHome, which can be used by an ESP32 in esp-idf, but a missing .h file stopped me and I have no idea what I do wrong. Here is what I do:
Created files:
- esphome
- components
- dcf77_2
- init.py
- dcf77_2_component.cpp
- dcf77_2_component.h
- time.py
- dcf77_2
- components
#time.py
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import time
import esphome.const as const
from esphome import pins
from esphome.const import (
CONF_PIN,
)
DEPENDENCIES = []
# C++ namespace
dcf77_2_ns = cg.esphome_ns.namespace("dcf77_2")
Dcf77Time_2 = dcf77_2_ns.class_("Dcf77Time_2", time.RealTimeClock, cg.Component)
CONFIG_SCHEMA = time.TIME_SCHEMA.extend({
cv.Required(const.CONF_ID): cv.declare_id(Dcf77Time_2),
cv.Required(CONF_PIN): pins.gpio_output_pin_schema,
})
async def to_code(config):
pin = await cg.gpio_pin_expression(config[CONF_PIN])
var = cg.new_Pvariable(config[const.CONF_ID], pin)
await cg.register_component(var, config)
await time.register_time(var, config)
//dcf77_2_component.h
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/time.h"
#include "esphome/components/time/real_time_clock.h"
//#include "DCF77.h"
//#include "TimeLib.h"
namespace esphome {
namespace dcf77_2 {
class Dcf77Time_2 : public time::RealTimeClock {
public:
explicit Dcf77Time_2(int pin) { this->pin_ = pin; }
//-----------------------------------------------------
// Initialize the components's hardware
//-----------------------------------------------------
void setup() override;
//-----------------------------------------------------
//
//-----------------------------------------------------
void loop() override;
//-----------------------------------------------------
//
//-----------------------------------------------------
void update() override;
protected:
InternalGPIOPin *pin_;
};
} // namespace dcf77_2
} // namespace esphome
//dcf77_2_component.cpp
#include "esphome/core/log.h"
#include "dcf77_2.h"
namespace esphome {
namespace dcf77_2 {
static const char *const TAG = "dcf77_2_time";
Dcf77Time_2::setup() {
this->dcf_ = new ::DCF77(this->pin_, digitalPinToInterrupt(this->pin_));
this->dcf_->Start();
ESP_LOGI(TAG, "DCF77 Decoder gestartet (Pin %d)", this->pin_);
}
void Dcf77Time_2::loop() {
}
void Dcf77Time_2::update() {
}
} // namespace dcf77_2
} // namespace esphome
#----------------------------------------------------
# wortuhr-3.yaml
#----------------------------------------------------
substitutions:
devicename: wortuhr-3
friendly_name: Wortuhr 3
device_description: Wortuhr 3
led_gpio: GPIO10
dcf_gpio: "3"
# for fritzbox it shall be .fritz.box, typically it shall be .local
network_domain: .fritz.box
# https://esphome.io/components/external_components/ dcf77_idf
external_components:
- source:
type: local
path: components
# https://esphome.io/components/esphome
esphome:
name: ${devicename}
# do not use friendly_name bause it will be added to entities
#friendly_name: ${friendly_name}
comment: ${device_description}
# https://esphome.io/components/esp32
esp32:
board: lolin_c3_mini
variant: esp32c3
framework:
type: esp-idf
# https://esphome.io/components/logger
# Enable logging
logger:
level: VERBOSE # VERY_VERBOSE # DEBUG # INFO
# https://esphome.io/components/time
# used for stand alone
time:
- platform: dcf77_2
id: dcf_time_source
pin: GPIO3
The validation works without an error, but the compiler:
INFO ESPHome 2025.10.4
INFO Reading configuration /config/esphome/wortuhr-3.yaml...
INFO Detected timezone 'Europe/Berlin'
INFO Generating C++ source...
INFO Compiling app...
Processing wortuhr-3 (board: lolin_c3_mini; framework: espidf; platform: https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-2/platform-espressif32.zip)
--------------------------------------------------------------------------------
INFO Package configuration completed successfully
INFO Package configuration completed successfully
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
- framework-espidf @ 3.50402.0 (5.4.2)
- tool-cmake @ 3.30.2
- tool-esp-rom-elfs @ 2024.10.11
- tool-esptoolpy @ 5.0.2
- tool-mklittlefs @ 3.2.0
- tool-ninja @ 1.13.1
- tool-scons @ 4.40801.0 (4.8.1)
- toolchain-riscv32-esp @ 14.2.0+20241119
Reading CMake configuration...
No dependencies
Compiling .pioenvs/wortuhr-3/src/esphome/components/dcf77_2/dcf77_2_component.cpp.o
Compiling .pioenvs/wortuhr-3/src/esphome/components/esp32/gpio.cpp.o
src/esphome/components/dcf77_2/dcf77_2_component.cpp:3:10: fatal error: dcf77_2.h: No such file or directory
***********************************************************************
* Looking for dcf77_2.h dependency? Check our library registry!
*
* CLI > platformio lib search "header:dcf77_2.h"
* Web > https://registry.platformio.org/search?q=header:%1B%5Bm%1B%5BKdcf77_2.h
*
***********************************************************************
3 | #include "dcf77_2.h"
| ^~~~~~~~~~~
compilation terminated.
*** [.pioenvs/wortuhr-3/src/esphome/components/dcf77_2/dcf77_2_component.cpp.o] Error 1
========================== [FAILED] Took 7.08 seconds ==========================
I use a terminal to check the files by ls src/esphome/components/dcf77_2/
and got: dcf77_2_component.cpp dcf77_2_component.h
So header file seems to be there.
I tried an example from: GitHub - jesserockz/esphome-external-component-examples
components/empty_binary_sensor
And this one worked as expectet.
Would be great if someone can give me a hint.