Register_service throws undefined reference at link time

Hi Homies !
I have a custom code that used to work fine (months ago) but does not compile any more as there are unresolved externals.

external_components:
  - source:
      type: git
      url: https://github.com/robertklep/esphome-custom-component
    components: [ custom, custom_component ]
...
custom_component:
 - id: cuart
   lambda: |-
       auto modBus = new esphome::customUARTComponent( id(mod_bus) );
       modBus->setrtspin( id(modbus_xmit) );
       App.register_component( modBus );
       auto vfd1 = new esphome::ModbusRTUDeviceVFD( 0x11, "vfd1" );
       vfd1->set_parent( modBus );
       App.register_component( vfd1 );
       auto vfd2 = new esphome::ModbusRTUDeviceVFD( 0x12, "vfd2" );
       vfd2->set_parent( modBus );
       App.register_component( vfd2 );
       vfd1->setup();
       vfd2->setup();       
       return { vfd1, vfd2 };      
...

the custom code invokes:
register_service(&ModbusRTUDeviceVFD::on_run, fullName( “run_motor” ), { “power” }) ;

the custom class is derived from CustomAPIDevice (already changed) and PollingComponent (used to be Component but loop was no longer envoked) as described here:
https://community.home-assistant.io/t/compile-problem-with-custom-component-and-register-service/494273

class ModbusRTUDevice : public PollingComponent, public CustomAPIDevice { …}

platformio_options:
build_flags: -DUSE_API_HOMEASSISTANT_STATES -DUSE_API_SERVICES
have been set but were already set correctly in defines.h user_services.h

The linker returns:

Linking .pioenvs/poolcontrol/firmware.elf
/data/cache/platformio/packages/toolchain-xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld: .pioenvs/poolcontrol/src/customuart/modbusDeviceVFD.cpp.o:(.literal._ZN7esphome3api18UserServiceDynamicIJiEE15execute_serviceERKNS0_21ExecuteServiceRequestE[_ZN7esphome3api18UserServiceDynamicIJiEE15execute_serviceERKNS0_21ExecuteServiceRequestE]+0x0): undefined reference to `_ZN7esphome3api21get_execute_arg_valueIiEET_RKNS0_22ExecuteServiceArgumentE'
/data/cache/platformio/packages/toolchain-xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld: .pioenvs/poolcontrol/src/customuart/modbusDeviceVFD.cpp.o:(.literal._ZN7esphome3api18UserServiceDynamicIJiEE28encode_list_service_responseEv[_ZN7esphome3api18UserServiceDynamicIJiEE28encode_list_service_responseEv]+0x0): undefined reference to `_ZN7esphome3api19to_service_arg_typeIiEENS0_5enums14ServiceArgTypeEv'
/data/cache/platformio/packages/toolchain-xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld: .pioenvs/poolcontrol/src/customuart/modbusDeviceVFD.cpp.o: in function `_ZN7esphome3api18UserServiceDynamicIJiEE8execute_INS_11FixedVectorINS0_22ExecuteServiceArgumentEEEJLi0EEEEvRKT_NS_3seqIJXspT0_EEEE':
/config/esphome/.esphome/build/poolcontrol/src/esphome/components/api/user_services.h:105:(.text._ZN7esphome3api18UserServiceDynamicIJiEE15execute_serviceERKNS0_21ExecuteServiceRequestE[_ZN7esphome3api18UserServiceDynamicIJiEE15execute_serviceERKNS0_21ExecuteServiceRequestE]+0x1b): undefined reference to `_ZN7esphome3api21get_execute_arg_valueIiEET_RKNS0_22ExecuteServiceArgumentE'
/data/cache/platformio/packages/toolchain-xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld: .pioenvs/poolcontrol/src/customuart/modbusDeviceVFD.cpp.o: in function `_ZN7esphome3api18UserServiceDynamicIJiEE28encode_list_service_responseEv':
/config/esphome/.esphome/build/poolcontrol/src/esphome/components/api/user_services.h:83:(.text._ZN7esphome3api18UserServiceDynamicIJiEE28encode_list_service_responseEv[_ZN7esphome3api18UserServiceDynamicIJiEE28encode_list_service_responseEv]+0x2a): undefined reference to `_ZN7esphome3api19to_service_arg_typeIiEENS0_5enums14ServiceArgTypeEv'
collect2: error: ld returned 1 exit status
**** [.pioenvs/poolcontrol/firmware.elf] Error 1*

The reason I implemented it as custom were that

  • My Modbus RTU uses echoing which was not supported then
  • many devices of different types share this Modbus connection (which might not be supported)

I also used to dynamically register sensors - which does not result in an error but the sensors do no longer appear. I have a workaround for that but don’t know why something that is supposed to work and has worked for years …
ESPHOME framework is actualized every month (or even more often) and every time it is a surprise what will fail next… I doubt switching to the “new concept” of external components will have any other benefit than causing even more work for user implementations not offered and new releases will be flooding with all there new features and new flaws :frowning:

Any help or do i have to drop the code and rewrite code outside of esphome ?

Has the issue been reported on GitHub to the author of the custom component?
You may find the support you need there. It may be just a tweak of the code is required and all is well.

You know that it is not obligatory to update every ESPHome device if it is working well?

In the interim, do you have a backup you can restore back to a version that was running?

Check the changes in respect of the ESPHome ModBus support in GitHub to verify if your required functionality has been added. You could raise a change request to get it added, or do what a lot of people have done, fork it and roll your own as it is open source.

Thank you for trying to help.
I have written that code by myself years ago and had to do it by custom integration as the modbus integration that time was terrible and even now would probably not be able to drive different device-types on the same bus (not sure about that).
I will try a different approach now and after it is functioning not update ANY ESPHOME component any more. I don’t need new “features” and am lucky enough once things run as they did before “improvements”.
Speech support sounds good - cloud not - the way ESPHOME moves is understandable but i won’t share.

It doesn’t have to be so extreme. Update just the ones that need it and leave others.

Looks like you are doing some kind of pool integration from the very limited info you posted.

Step back and look at the bigger picture of what is available now. Maybe one of the other MODBUS solutions around may be more suitable and require less code maintenance. Maybe the need for a custom component is not necessary any more as the standard software matures and the required functionality is added.

ESPHome posts breaking changes in the update documentation. I always read that very carefully and take note of any deprecated warnings before I hit the update button. I recommend you take the same approach to prevent surprises.

Share your code is one way of putting back into the open source community. ‘Pay it forward’ is a fantastic life concept to adopt.

Sure but I simply do not have the will and time to read all that release notes and judge their effect on my current devices. And what if they might require hours of rework - stop updating from then onwards ?

I better deal with esp-idf updates coming less often, being better documented and program there having MQTT- as a link to HA-UI.

The way the HA environment is administrated in the last years is too unstable for me, of course the system is becoming more “mature” (and more commercial) which does not mean better necessarily.

“Paying back” sure is a nice approach but not many people might need 4-stepper motors attached to a PCF8541 or 3 different devices attached to a single Modbus-Port.

But a linkage failure of an “ecosystem” (and the fact hundreds of sources are compiled) is showing that the development crowd makes a good but not perfect job.

We had a project with more than 500 source files but if you changed one of them only the relevant changes were compiled and put in a library. Maybe things have changed for a reason but each change of the YAML results in 10mins compilation and modules as BLE, Crypto and stuff never being used are being compiled every time … if i want a full build i can do it by myself !

Why should i need a core update ? An update of esphome, of MQTT, Grafana or anything else if i am satisfied with what i have (rather not right now) ?

I mean all that recent updates have not been of any benefits for me besides the feeling - my system is actual right now :slight_smile: