Ecosmart Hot Water Heater Remote

Is there anyone who has implemented @PhilRW code for an EcoSmart Hot Water Heater Remote: GitHub - PhilRW/ecosmart-remote: Remote control for EcoSmart tankless water heaters

I have an ESP8266 and an EcoSmart27 Hot water heater that I would love to control but I am not understanding the repo and how to implement it with my HomeAssistant setup. I have the ESPHome addon and have successfully got a relay working but I am less familiar with MQTT.

I am hoping someone here could offer guidance in order to help get me going.

Thanks!

I updated the repo with ESPHome-specific instructions; it should be a bit easier to integrate now.

As always, I make no warranties as to whether this will work for you - but it did work for me on my particular model. And watch out connecting those control wires! I fried a controller just looking at it funny. :slight_smile:

One thing I didn’t mention is that the metal enclosure of the EcoSmart was really a hindrance to the nodemcu wifi signal. I had to place an AP pretty close to it to get it to work. I also could have brought the control wires through the case and placed the nodemcu on the outside.

Thanks @PhilRW

I attempted an install but got stuck a bit. First error I got was with the status pin declaration. I changed D0 to 0 and the error went away.

Then I got an error when compiling where I get an error about BinarySensor.

src/ecosmart.h:234:61: error: no matching function for call to 'esphome::binary_sensor::BinarySensor::BinarySensor(const char [12])'
  234 |   BinarySensor *flow_sensor = new BinarySensor("Flow Sensor");
      |                                                             ^
In file included from src/esphome/core/controller.h:5,
                 from src/esphome/components/api/api_server.h:4,
                 from src/esphome/components/api/api_connection.h:6,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/components/binary_sensor/binary_sensor.h:28:12: note: candidate: 'esphome::binary_sensor::BinarySensor::BinarySensor()'
   28 |   explicit BinarySensor();
      |            ^~~~~~~~~~~~
src/esphome/components/binary_sensor/binary_sensor.h:28:12: note:   candidate expects 0 arguments, 1 provided
src/esphome/components/binary_sensor/binary_sensor.h:26:7: note: candidate: 'esphome::binary_sensor::BinarySensor::BinarySensor(const esphome::binary_sensor::BinarySensor&)'
   26 | class BinarySensor : public EntityBase {
      |       ^~~~~~~~~~~~
src/esphome/components/binary_sensor/binary_sensor.h:26:7: note:   no known conversion for argument 1 from 'const char [12]' to 'const esphome::binary_sensor::BinarySensor&'
src/esphome/components/binary_sensor/binary_sensor.h:26:7: note: candidate: 'esphome::binary_sensor::BinarySensor::BinarySensor(esphome::binary_sensor::BinarySensor&&)'
src/esphome/components/binary_sensor/binary_sensor.h:26:7: note:   no known conversion for argument 1 from 'const char [12]' to 'esphome::binary_sensor::BinarySensor&&'
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/lib84c/IRremoteESP8266/ir_Sherwood.cpp.o
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/lib84c/IRremoteESP8266/ir_Sony.cpp.o
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/lib84c/IRremoteESP8266/ir_Symphony.cpp.o
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/lib84c/IRremoteESP8266/ir_Tcl.cpp.o
*** [/data/esp3-ecosmart/.pioenvs/esp3-ecosmart/src/main.cpp.o] Error 1

Any thoughts on this?

I went ahead and commented out the binary_sensor and the climate sections of the yaml and attempted to recompile. I then got new errors (several) this time with regard to ecosmart.h

In file included from src/main.cpp:28:
src/ecosmart.h:57:1: error: expected class-name before '{' token
   57 | {
      | ^
src/ecosmart.h:91:3: error: 'ClimateTraits' does not name a type
   91 |   ClimateTraits traits() override
      |   ^~~~~~~~~~~~~
src/ecosmart.h:108:22: error: 'ClimateCall' does not name a type
  108 |   void control(const ClimateCall &call) override
      |                      ^~~~~~~~~~~
src/ecosmart.h:108:8: error: 'void EcoSmartClimate::control(const int&)' marked 'override', but does not override
  108 |   void control(const ClimateCall &call) override
      |        ^~~~~~~
src/ecosmart.h: In member function 'virtual void EcoSmartClimate::setup()':
src/ecosmart.h:74:26: error: 'class EcoSmartClimate' has no member named 'restore_state_'
   74 |     auto restore = this->restore_state_();
      |                          ^~~~~~~~~~~~~~
src/ecosmart.h:81:13: error: 'class EcoSmartClimate' has no member named 'mode'
   81 |       this->mode = climate::CLIMATE_MODE_HEAT;
      |             ^~~~
src/ecosmart.h:81:20: error: 'climate' has not been declared
   81 |       this->mode = climate::CLIMATE_MODE_HEAT;
      |                    ^~~~~~~
src/ecosmart.h:82:13: error: 'class EcoSmartClimate' has no member named 'current_temperature'
   82 |       this->current_temperature = NAN;
      |             ^~~~~~~~~~~~~~~~~~~
src/ecosmart.h:84:21: error: 'class EcoSmartClimate' has no member named 'target_temperature'
   84 |     if (isnan(this->target_temperature))
      |                     ^~~~~~~~~~~~~~~~~~
src/ecosmart.h:86:13: error: 'class EcoSmartClimate' has no member named 'target_temperature'
   86 |       this->target_temperature = ECOSMART_TEMP_MIN;
      |             ^~~~~~~~~~~~~~~~~~
src/ecosmart.h:88:11: error: 'class EcoSmartClimate' has no member named 'publish_state'
   88 |     this->publish_state();
      |           ^~~~~~~~~~~~~
src/ecosmart.h: In member function 'void EcoSmartClimate::control(const int&)':
src/ecosmart.h:112:14: error: request for member 'get_mode' in 'call', which is of non-class type 'const int'
  112 |     if (call.get_mode().has_value())
      |              ^~~~~~~~
src/ecosmart.h:115:7: error: 'ClimateMode' was not declared in this scope; did you mean 'esphome::api::enums::ClimateMode'?
  115 |       ClimateMode mode = *call.get_mode();
      |       ^~~~~~~~~~~
      |       esphome::api::enums::ClimateMode
In file included from src/esphome/components/api/api_connection.h:4,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/components/api/api_pb2.h:83:6: note: 'esphome::api::enums::ClimateMode' declared here
   83 | enum ClimateMode : uint32_t {
      |      ^~~~~~~~~~~
In file included from src/main.cpp:28:
src/ecosmart.h:117:15: error: 'mode' was not declared in this scope; did you mean 'modf'?
  117 |       switch (mode)
      |               ^~~~
      |               modf
src/ecosmart.h:119:12: error: 'climate' has not been declared
  119 |       case climate::CLIMATE_MODE_OFF:
      |            ^~~~~~~
src/ecosmart.h:122:12: error: 'climate' has not been declared
  122 |       case climate::CLIMATE_MODE_HEAT:
      |            ^~~~~~~
In file included from src/esphome/components/api/proto.h:4,
                 from src/esphome/components/api/api_pb2.h:5,
                 from src/esphome/components/api/api_connection.h:4,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/ecosmart.h:126:86: error: 'class EcoSmartClimate' has no member named 'mode'
  126 |         ESP_LOGE(TAG, "Climate mode not supported: %s", climate_mode_to_string(this->mode));
      |                                                                                      ^~~~
src/esphome/core/log.h:123:89: note: in definition of macro 'esph_log_e'
  123 |   esp_log_printf_(ESPHOME_LOG_LEVEL_ERROR, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                         ^~~~~~~~~~~
src/ecosmart.h:126:9: note: in expansion of macro 'ESP_LOGE'
  126 |         ESP_LOGE(TAG, "Climate mode not supported: %s", climate_mode_to_string(this->mode));
      |         ^~~~~~~~
src/ecosmart.h:126:57: error: 'climate_mode_to_string' was not declared in this scope
  126 |         ESP_LOGE(TAG, "Climate mode not supported: %s", climate_mode_to_string(this->mode));
      |                                                         ^~~~~~~~~~~~~~~~~~~~~~
src/esphome/core/log.h:123:89: note: in definition of macro 'esph_log_e'
  123 |   esp_log_printf_(ESPHOME_LOG_LEVEL_ERROR, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                         ^~~~~~~~~~~
src/ecosmart.h:126:9: note: in expansion of macro 'ESP_LOGE'
  126 |         ESP_LOGE(TAG, "Climate mode not supported: %s", climate_mode_to_string(this->mode));
      |         ^~~~~~~~
In file included from src/main.cpp:28:
src/ecosmart.h:131:13: error: 'class EcoSmartClimate' has no member named 'mode'
  131 |       this->mode = mode;
      |             ^~~~
src/ecosmart.h:131:20: error: 'mode' was not declared in this scope; did you mean 'modf'?
  131 |       this->mode = mode;
      |                    ^~~~
      |                    modf
src/ecosmart.h:138:14: error: request for member 'get_target_temperature' in 'call', which is of non-class type 'const int'
  138 |     if (call.get_target_temperature().has_value())
      |              ^~~~~~~~~~~~~~~~~~~~~~
src/ecosmart.h:141:41: error: request for member 'get_target_temperature' in 'call', which is of non-class type 'const int'
  141 |       float temp_c = clamp<float>(*call.get_target_temperature(), ECOSMART_TEMP_MIN, ECOSMART_TEMP_MAX);
      |                                         ^~~~~~~~~~~~~~~~~~~~~~
src/ecosmart.h:145:13: error: 'class EcoSmartClimate' has no member named 'target_temperature'
  145 |       this->target_temperature = temp_c;
      |             ^~~~~~~~~~~~~~~~~~
src/ecosmart.h: In member function 'void EcoSmartClimate::sendCommand()':
src/ecosmart.h:227:11: error: 'class EcoSmartClimate' has no member named 'publish_state'
  227 |     this->publish_state();
      |           ^~~~~~~~~~~~~
src/ecosmart.h: At global scope:
src/ecosmart.h:234:3: error: 'BinarySensor' does not name a type
  234 |   BinarySensor *flow_sensor = new BinarySensor("Flow Sensor");
      |   ^~~~~~~~~~~~
src/ecosmart.h: In member function 'void EcoSmart::processData(uint64_t)':
src/ecosmart.h:391:14: error: 'class EcoSmartClimate' has no member named 'target_temperature'
  391 |     climate->target_temperature = lroundf(use_c ? getTempC() : getTempF());
      |              ^~~~~~~~~~~~~~~~~~
src/ecosmart.h:392:14: error: 'class EcoSmartClimate' has no member named 'mode'
  392 |     climate->mode = stateOn ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_OFF;
      |              ^~~~
src/ecosmart.h:392:31: error: 'climate' is not a class, namespace, or enumeration
  392 |     climate->mode = stateOn ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_OFF;
      |                               ^~~~~~~
src/ecosmart.h:392:60: error: 'climate' is not a class, namespace, or enumeration
  392 |     climate->mode = stateOn ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_OFF;
      |                                                            ^~~~~~~
src/ecosmart.h:393:14: error: 'class EcoSmartClimate' has no member named 'publish_state'
  393 |     climate->publish_state();
      |              ^~~~~~~~~~~~~
src/ecosmart.h:395:5: error: 'flow_sensor' was not declared in this scope
  395 |     flow_sensor->publish_state(stateFlow);
      |     ^~~~~~~~~~~
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/FrameworkArduino/core_esp8266_spi_utils.cpp.o
Compiling /data/esp3-ecosmart/.pioenvs/esp3-ecosmart/FrameworkArduino/core_esp8266_timer.cpp.o
*** [/data/esp3-ecosmart/.pioenvs/esp3-ecosmart/src/main.cpp.o] Error 1

Unfortunately I lost my EcoSmart heater in a wildfire (not caused by the heater), so maintenance is not my priority at this point, but when I re-implement it I will try to work out the bugs. Are you using the ecosmart.h file from the ecosmart directory?

Yes, I have put the ecosmart.h file (https://github.com/PhilRW/ecosmart-remote/blob/d4bee5ff02f93464ac36f4cd8412520438f0544a/esphome/ecosmart.h) into the esphome directory.