geoffdavis / esphome-mitsubishiheatpump

ESPHome Climate Component for Mitsubishi Heatpumps using direct serial connection
BSD 2-Clause "Simplified" License
560 stars 153 forks source link

Compile error with callback lambdas #26

Closed thompsa closed 3 years ago

thompsa commented 3 years ago
Compiling .pioenvs/heatpump/src/esphome-mitsubishiheatpump/espmhp.cpp.o
Compiling .pioenvs/heatpump/src/main.cpp.o
src/esphome-mitsubishiheatpump/espmhp.cpp: In member function 'virtual void MitsubishiHeatPump::setup()':
src/esphome-mitsubishiheatpump/espmhp.cpp:421:5: error: no matching function for call to 'HeatPump::setSettingsChangedCallback(MitsubishiHeatPump::setup()::<lambda()>)'
     );
     ^
In file included from src/esphome-mitsubishiheatpump/espmhp.h:21:0,
                 from src/esphome-mitsubishiheatpump/espmhp.cpp:18:
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:232:10: note: candidate: void HeatPump::setSettingsChangedCallback(void (*)())
     void setSettingsChangedCallback(SETTINGS_CHANGED_CALLBACK_SIGNATURE);
          ^
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:232:10: note:   no known conversion for argument 1 from 'MitsubishiHeatPump::setup()::<lambda()>' to 'void (*)()'
src/esphome-mitsubishiheatpump/espmhp.cpp:427:5: error: no matching function for call to 'HeatPump::setStatusChangedCallback(MitsubishiHeatPump::setup()::<lambda(heatpumpStatus)>)'
     );
     ^
In file included from src/esphome-mitsubishiheatpump/espmhp.h:21:0,
                 from src/esphome-mitsubishiheatpump/espmhp.cpp:18:
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:233:10: note: candidate: void HeatPump::setStatusChangedCallback(void (*)(heatpumpStatus))
     void setStatusChangedCallback(STATUS_CHANGED_CALLBACK_SIGNATURE);
          ^
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:233:10: note:   no known conversion for argument 1 from 'MitsubishiHeatPump::setup()::<lambda(heatpumpStatus)>' to 'void (*)(heatpumpStatus)'
*** [.pioenvs/heatpump/src/esphome-mitsubishiheatpump/espmhp.cpp.o] Error 1

The issue seems to be that you can not cast a lambda function with a non-empty capture to a void fn pointer. This seems non-trivial to overcome, lots of posts about using templates however beyond my understanding.

geoffdavis commented 3 years ago

I'm not quite sure how you are getting this error - thus I'm assuming that your instantiation is somehow different than mine. I have callbacks enabled in my active code base and no compilation errors. Are you doing something different than the example instantiation?

# Enable logging
logger:
  # ESP8266 only - disable serial port logging, as the HeatPump component
  # needs the sole hardware UART on the ESP8266
  baud_rate: 0

climate:
  - platform: custom
    # ESP32 only - change &Serial to &Serial1 or &Serial2 and remove the
    # logging:baud_rate above to allow the built-in UART0 to function for
    # logging.
    lambda: |-
      auto my_heatpump = new MitsubishiHeatPump(&Serial);
      App.register_component(my_heatpump);
      return {my_heatpump};
    climates:
      - name: "${friendly_name}"
thompsa commented 3 years ago

I should have included my config, here it is. I don't think it is different to the example in any significant way. I am compiling on OSX (11.1) although I have also just tried on Linux with the same result.

esphome:
  name: heatpump
  platform: ESP32
  board: esp-wrover-kit

  libraries:
    - SwiCago/HeatPump

  includes:
    - esphome-mitsubishiheatpump

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_pass

# Enable logging
logger:
  level: DEBUG
  # baud_rate: 0

# Enable Home Assistant API
api:

ota:
  safe_mode: True
  password: !secret ota_pass

climate:
  - platform: custom
    # ESP32 only - change &Serial to &Serial1 or &Serial2 and remove the
    # logging:baud_rate above to allow the built-in UART0 to function for
    # logging.
    lambda: |-
      auto my_heatpump = new MitsubishiHeatPump(&Serial2);
      App.register_component(my_heatpump);
      return {my_heatpump};
    climates:
      - name: "Heatpump"

Here is the log.


% esphome heatpump.yaml compile 
INFO Reading configuration heatpump.yaml...
INFO Generating C++ source...
INFO Compiling app...
INFO Running:  platformio run -d heatpump
*****************************************************************************************************************************************************
Obsolete PIO Core v5.0.4 is used (previous was 5.1.0)
Please remove multiple PIO Cores from a system:
https://docs.platformio.org/page/faq.html#multiple-platformio-cores-in-a-system
*****************************************************************************************************************************************************
Processing heatpump (board: esp-wrover-kit; framework: arduino; platform: espressif32@1.12.4)
-----------------------------------------------------------------------------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES: 
 - framework-arduinoespressif32 3.10004.210126 (1.0.4) 
 - tool-esptoolpy 1.20600.0 (2.6.0) 
 - toolchain-xtensa32 2.50200.80 (5.2.0)
Library Manager: Installing Hash
Warning! Could not find the package with 'Hash' requirements for your system 'darwin_arm64'
Dependency Graph
|-- <AsyncTCP-esphome> 1.1.1
|-- <ESPmDNS> 1.0
|   |-- <WiFi> 1.0
|-- <HeatPump> 1.0.0
|-- <Update> 1.0
|-- <WiFi> 1.0
Compiling .pioenvs/heatpump/src/esphome-mitsubishiheatpump/espmhp.cpp.o
Compiling .pioenvs/heatpump/src/esphome/core/scheduler.cpp.o
Compiling .pioenvs/heatpump/src/esphome/core/util.cpp.o
Compiling .pioenvs/heatpump/src/main.cpp.o
Generating partitions .pioenvs/heatpump/partitions.bin
Compiling .pioenvs/heatpump/libbb3/AsyncTCP-esphome/AsyncTCP.cpp.o
Compiling .pioenvs/heatpump/libefd/WiFi/ETH.cpp.o
Compiling .pioenvs/heatpump/libefd/WiFi/WiFi.cpp.o
Compiling .pioenvs/heatpump/libefd/WiFi/WiFiAP.cpp.o
src/esphome-mitsubishiheatpump/espmhp.cpp: In member function 'virtual void MitsubishiHeatPump::setup()':
src/esphome-mitsubishiheatpump/espmhp.cpp:421:5: error: no matching function for call to 'HeatPump::setSettingsChangedCallback(MitsubishiHeatPump::setup()::<lambda()>)'
     );
     ^
In file included from src/esphome-mitsubishiheatpump/espmhp.h:21:0,
                 from src/esphome-mitsubishiheatpump/espmhp.cpp:18:
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:232:10: note: candidate: void HeatPump::setSettingsChangedCallback(void (*)())
     void setSettingsChangedCallback(SETTINGS_CHANGED_CALLBACK_SIGNATURE);
          ^
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:232:10: note:   no known conversion for argument 1 from 'MitsubishiHeatPump::setup()::<lambda()>' to 'void (*)()'
src/esphome-mitsubishiheatpump/espmhp.cpp:427:5: error: no matching function for call to 'HeatPump::setStatusChangedCallback(MitsubishiHeatPump::setup()::<lambda(heatpumpStatus)>)'
     );
     ^
In file included from src/esphome-mitsubishiheatpump/espmhp.h:21:0,
                 from src/esphome-mitsubishiheatpump/espmhp.cpp:18:
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:233:10: note: candidate: void HeatPump::setStatusChangedCallback(void (*)(heatpumpStatus))
     void setStatusChangedCallback(STATUS_CHANGED_CALLBACK_SIGNATURE);
          ^
.piolibdeps/heatpump/HeatPump/src/HeatPump.h:233:10: note:   no known conversion for argument 1 from 'MitsubishiHeatPump::setup()::<lambda(heatpumpStatus)>' to 'void (*)(heatpumpStatus)'
*** [.pioenvs/heatpump/src/esphome-mitsubishiheatpump/espmhp.cpp.o] Error 1
============================================================ [FAILED] Took 4.78 seconds ============================================================```
geoffdavis commented 3 years ago

If that's the entirety of your configuration, then I think you are missing the setup routine for Serial1. On the ESP32, you still have to setup the device before you can reference it.

I got it to work once on an ESP32 during debugging but I cannot for the life of my find where that test code went.

geoffdavis commented 3 years ago

I think that if you declare a UART resource section for uart1, and assign a couple of pins to that UART, it will as a side effect initialize the Serial1 variable at the Arduino layer.

geoffdavis commented 3 years ago

Now that I think about this, I had actually asked the maintainer of the HeatPump Arduino library to modify the constructor so that I could pass in an arbitrary pre-initialized serial-like device, but he wasn't a big fan of the idea and I ran out of time to do it myself. See https://github.com/SwiCago/HeatPump/issues/154

thompsa commented 3 years ago

I have an ESP8266 module so I will test with that and report back. The ESP32 is a little easier as it has internal pullup resistors so it can connect direct to the HP, I had this unit using https://github.com/unixko/MitsuCon for some time but was hoping to move to esphome and avoid mqtt + HA custom component. I'll also look into the UART initialisation.

geoffdavis commented 3 years ago

I think you can also disable the hardware logging as per the ESP8266 instructions and just use the ESP32's default pins for UART0.

geoffdavis commented 3 years ago

Hmm, after monkeying with this a bit, there's definitely a bug in my callback code unrelated to the UART setup. Not sure why it's working in ESP8266-land but not on ESP32 any more. I'll have to dig a bit.

geoffdavis commented 3 years ago

FWIW you can use the simple voltage divider method to get the level shift working on the ESP8266. I did a very cheesy perf-board thing with ESP_01S modules for my three units.

oddeirik commented 3 years ago

I encountered this issue with a mismatched callback signature as well, and the solution? Make sure you specify the heatpump library with the full Github URL:

  libraries:
    - https://github.com/SwiCago/HeatPump

(Note the https://github.com/ in front to force a package retrieval )

It seems that it's fetching an outdated version of the HeatPump library otherwise. In the version used without the full library URL, the callback signatures defined are lacking the ESP8266/ESP32 macros.

The callback signature for ESP32 was added in this commit, over a year ago: https://github.com/SwiCago/HeatPump/commit/7c887c8ff4587a4eed3d2bcdcea40c4aecb63311

Edit: Just downloaded and checked the Heatpump platformio package (which seems to be what esphome uses as its tooling) and it's out-of-date compared to what's on Github: https://platformio.org/lib/show/7096/HeatPump/installation

thompsa commented 3 years ago

This resolves the compile issue for me, thanks @oddeirik.

geoffdavis commented 3 years ago

Thanks @oddeirik , I'll update the readme.