Error compiling for ArduinoIoTCloud with M5StickCPlus



  • I have been using Arduino IoT Cloud successfully with an M5Atom for a while, creating Things with cloud variables controlled by Dashboards, such as using a button on a Dashboard change the color of the LED. I tried doing something similar with an M5StickCPlus with a simple sketch using the template provided by IoT Cloud to change the color of the LCD display:

    #include "arduino_secrets.h"
    /* 
      Sketch generated by the Arduino IoT Cloud Thing "Untitled"
      https://create.arduino.cc/cloud/things/e393cc1c-d5b7-48bb-8a27-521dxxxxxxx
    
      Arduino IoT Cloud Variables description
    
      The following variables are automatically generated and updated when changes are made to the Thing
    
      bool button;
    
      Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
      which are called when their values are changed from the Dashboard.
      These functions are generated with the Thing and added at the end of this sketch.
    */
    
    #include "thingProperties.h"
    #include "M5StickCPlus.h"
    
    void setup() {
      M5.begin();
    
      // Defined in thingProperties.h
      initProperties();
    
      // Connect to Arduino IoT Cloud
      ArduinoCloud.begin(ArduinoIoTPreferredConnection);
      
    void loop() {
      ArduinoCloud.update();
      // Your code here 
    }
    
    /*
      Since Button is READ_WRITE variable, onButtonChange() is
      executed every time a new value is received from IoT Cloud.
    */
    void onButtonChange()  {
      // Add your code here to act upon Button change
      if (button)
        M5.Lcd.fillScreen(RED);
      else
        M5.Lcd.fillScreen(BLUE);
    }
    

    When I compile this, I get the following error:

    c:\Users\xxx\Documents\Arduino\libraries\M5StickCPlus\src/utility/In_eSPI.h:952:52: error: macro "setAttribute" passed 2 arguments, but takes just 1
    			     void setAttribute(uint8_t id = 0, uint8_t a = 0);
    

    The problem is that ArduinoIoTCloud.h includes a file property/Property.h that defines three macros, including setAttribute

    #define appendAttributesToCloud() appendAttributesToCloudReal(CborEncoder *encoder)
    #define appendAttribute(x) appendAttributeReal(x, getAttributeName(#x, '.'), encoder)
    #define setAttribute(x) setAttributeReal(x, getAttributeName(#x, '.'))
    

    Unfortunately, there is a class member function called setAttribute in the library file M5StickCPlus/src/utility/In_eSPI.h

    // Set or get an arbitrary library attribute or configuration option
        void setAttribute(uint8_t id = 0, uint8_t a = 0);
        uint8_t getAttribute(uint8_t id = 0);
    

    Because the macro from the ArduinoIoTCloud library is included globally, it ends up getting used in place of the correct function (which has 2 arguments).

    Whose "fault" is this and what should be the fix? In general, I think it's not good form to include a global macro in a library, especially one with a name like setAttribute that could easily match something in user code that includes that library. So I decided to change my local copy of the ArduinoIoTCloud library and replace the macro name with AIOTC_setAttribute (as well as prefixing the other two macros with AIOTC_), and then modify all of the files in property/types that use this macro to match.

    Hopefully someone finds this helpful. I'm going to post this over on the Arduino forum as well, as I think these global macros should be replaced by something safer.