Editing builtin component using External Components

I’m trying to modify the Tuya Climate component. My TuyaMCU reports temperature in Fahrenheit but ESPHome interprets it as Celsius. When Home Assistant imports the value it converts it back to F, resulting in values like 150degF (since the original value was considered 65 degC). There’s a temperature multiplier I can use in the Tuya Climate component, but that’s not enough to convert from F to C. So I was going to modify the .cpp file to include "- 32" and then use the available multiplier.

I’d like to use the external components feature to copy the existing “tuya” directory from my cache or github, and modify the file locally. But i’m not having any luck. I’ve read through most of the relevant ESPhome documentation, I think, at least without fully diving in to learning how to develop/contribute. I’m stuck on needing to set up a config schema.

Failed config

tuya: [source /config/esphome/bathroomheater.yaml:22]
  
  Component tuya cannot be loaded via YAML (no CONFIG_SCHEMA).
  {}
climate.tuya: [source /config/esphome/bathroomheater.yaml:43]
  
  Component climate.tuya cannot be loaded via YAML (no CONFIG_SCHEMA).

I’ve found a few examples online, and I could probably struggle my way through making one that would work for this situation, but I don’t think I should need to do that since the existing component doesn’t have any .py files defining a config_schema. I searched my whole esphome directory for any .py files, and there are only a few in my custom components directory, so I don’t think there’s one hiding for any of the default components that I could just copy.

What triggers the requirement for a config schema? Or how can I manage to copy a built in component and edit only a single .cpp file? I’m sure I could create a few template sensors in ESPHome and build a custom climate device in home assistant, but i’d rather figure out how to use these external components.

Progress. I found the init.py files are on github, but not in my local cache directory. They define the config_schema, so that issue is taken care of. But now I’m running into trouble I believe with the fact that the component I need to modify is in a subfolder. If i copy the whole tuya directory, including the climate subdirectory which contains the .cpp file I want to edit, then I get errors

src/esphome/components/tuyaGithub/climate/tuya_climate.cpp:48:20: error: 'class esphome::tuya::Tuya' has no member named 'set_datapoint_value'
     this->parent_->set_datapoint_value(datapoint);

That’s when my yaml looks like

external_components:
  - source:
      type: local
      path: my_components
    components: [ tuyaGithub ]
... 
climate:
  - platform: tuyaGithub
    name: "HeatStorm"

I’ve also tried copying just the climate subdirectory into the my_components directory, but that also results in errors because the python file references some namespace in the parent directory which no longer exists in this case.

I started a new project and that seemed to solve some issues, I must have inadvertently edited one of the files somewhere. I copied the tuya directory into my_components directory. I’m now able to compile and make edits to my_components/tuya/climate/tuya_climate.cpp, but my simple F to C issue wasn’t the end of my debugging and now I need to edit a file - my_components/tuya/tuya.cpp. For some reason, even though my edits to the file in the “climate” subdirectory work, the edits to the file tuya.cpp in the “tuya” directory do not get picked up. I’m guessing it’s to with my lack of understanding in how the names in yaml relate to the names used in the cpp and py files.

i think i need to change “tuya:” to “tuyaGithub:”

external_components:
  - source:
      type: local
      path: my_components
    components: [ tuyaGithub ]
...
tuya:

climate:
  - platform: tuyaGithub
    name: "HeatStorm"
external_components:
  - source:
      type: local
      path: my_components
    components: [ tuyaGithub ]
...
tuyaGithub:

climate:
  - platform: tuyaGithub
    name: "HeatStorm"

But when I do that, I get an error that the climate platform tuyaGithub, requires component tuya. I’m not sure what file or line i need to edit to read tuyaGithub so that i’ll be allowed to compile. I tried changing something in the config_schema but that didn’t make the tooltip disappear.

Finally got everything working. I ended up not needing to edit tuya.cpp, only tuya_climate.cpp, so i didn’t have to figure out how to make tuya.cpp work.

For reference, I have a Heat Storm heater that I flashed the on board TYW3ES over to ESPHome. The TuyaMCU reports current temp and commanded temp in datapoints 21 and 20, but it reports them as Fahrenheit and ESPHome interprets them in Celsius, so values in Home Assistant get converted twice and end up wrong. Here’s what i changed to make it work. It’s a little ugly, i might try to do some rounding so things look nicer, but it works for now.

esphome:
  name: bathroomheater

external_components:
  - source:
      type: local
      path: my_components
    components: [ tuyaGithub ]

esp8266:
  board: esp01_1m

# Enable logging
logger:
  baud_rate: 0
  level: VERBOSE
uart:
  rx_pin: GPIO3
  tx_pin: GPIO1
  baud_rate: 9600
  
  

tuya:

# Enable Home Assistant API
api:

ota:

wifi:
  ssid: xxx
  password: xxx

climate:
  - platform: tuyaGithub
    name: "HeatStorm"
    id: heat_storm
    switch_datapoint: 1
    target_temperature_datapoint: 20
    current_temperature_datapoint: 21
    current_temperature_multiplier: 0.55
    target_temperature_multiplier: 0.55

I changed only two spots the tuya_climate.cpp file to convert the temperature, subtracting 32 and then adding 32 back in later. I used the built in multiplier for the other part of the conversion.

if (this->target_temperature_id_.has_value()) {
    this->parent_->register_listener(*this->target_temperature_id_, [this](const TuyaDatapoint &datapoint) {
      this->manual_temperature_ = (datapoint.value_int - 32 ) * this->target_temperature_multiplier_;
      ESP_LOGV(TAG, "MCU reported manual target temperature is: %.1f", this->manual_temperature_);
      this->compute_target_temperature_();
      this->compute_state_();
      this->publish_state();
  if (call.get_target_temperature().has_value()) {
    const float target_temperature = *call.get_target_temperature();
    ESP_LOGV(TAG, "Setting target temperature: %.1f", target_temperature);
    ESP_LOGV(TAG, "final: %.1f", target_temperature_final);
    this->parent_->set_integer_datapoint_value(*this->target_temperature_id_,
                                               (int) ((target_temperature  / this->target_temperature_multiplier_) + 32 ));

1 Like

So you just change the name of the folder from tuya to something other and it magically works?

Update: well for now I did without checking datapoint type, just make it work as it is custom component and it works as you described! So helpful.

So if anyone has heater

  • klarstein Hot Spot Crystal Spotless Smart
  • Termofol TF-750W
  • Kogan glass panel heater

this fixes eco mode issue when using esphome

Is there a way to get datapoint type without modifying tuya.h to expose `get_datapoints_``?

Do you mind sharing how you flashed it over to ESPHome?