Setting up VSCode and PlatformIO to support development with ESP Rainmaker

Hello,
For my development on ESP32, I am using VSCode and PlatformIO. I enjoy this much, thanks!
I also installed the Arduino IDE on my machine for testing.
I tried the simple ESP Rainmaker Switch sample code with the Arduino IDE. It complied, loaded to my ESP32 and run with no issues.
Before that, I tried to do the same with VSCode & PlatformIO and encountered the following issues:

  • Same code that took about 59% Flash using the Arduino IDE, took almost 92% with VSCode
  • Some of the functions (e.g. the included App Insignts header, RMaker.enableScenes();, initAppInsights();, and RMaker.enableSystemService(SYSTEM_SERV_FLAGS_ALL, 2, 2, 2); - where not recognized (produced compile errors). I commented these out, compiled, and uploaded to the ESP32, but nothing happend (no output at all to the terminal and no way to provision). Looks like I am doing something wrong.
    Can you please help in setting Rainmaker to be used with VSCode and PlatformIO?
    Thanks a lot!

Could you provide a simple code to reproduce this issue?

cc: @valeros

Hi Ivan,
I used the sample code from the Rainmaker samples provided with the arduino-esp32 package that is installed in the Arduino IDE. Just go to the Rainmaker samples in the Arduino IDE and take the Switch sample code. I will also try to paste in the code when I reach home tonight.
I will highly appreciate it if you can provide instruction how to setup VSCode+PlatformIO for use with Rainmaker, including the required partitions table (there is a specific partition table that needs to be selected in the Arduino IDE for utilizing Rainmaker).
Thanks a lot!!!

Here is the example code:

// This example demonstrates the ESP RainMaker with a standard Switch device.
#include "RMaker.h"
#include "WiFi.h"
#include "WiFiProv.h"
#include "AppInsights.h"

#define DEFAULT_POWER_MODE true
const char *service_name = "PROV_1234";
const char *pop = "abcd1234";

// GPIO for push button
#if CONFIG_IDF_TARGET_ESP32C3
static int gpio_0 = 9;
static int gpio_switch = 7;
#else
// GPIO for virtual device
static int gpio_0 = 0;
static int gpio_switch = 16;
#endif

/* Variable for reading pin status*/
bool switch_state = true;

// The framework provides some standard device types like switch, lightbulb,
// fan, temperaturesensor.
static Switch *my_switch = NULL;

void sysProvEvent(arduino_event_t *sys_event)
{
    switch (sys_event->event_id) {
    case ARDUINO_EVENT_PROV_START:
#if CONFIG_IDF_TARGET_ESP32S2
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n",
                      service_name, pop);
        printQR(service_name, pop, "softap");
#else
        Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n",
                      service_name, pop);
        printQR(service_name, pop, "ble");
#endif
        break;
    case ARDUINO_EVENT_PROV_INIT:
        wifi_prov_mgr_disable_auto_stop(10000);
        break;
    case ARDUINO_EVENT_PROV_CRED_SUCCESS:
        wifi_prov_mgr_stop_provisioning();
        break;
    default:;
    }
}

void write_callback(Device *device, Param *param, const param_val_t val,
                    void *priv_data, write_ctx_t *ctx)
{
    const char *device_name = device->getDeviceName();
    const char *param_name = param->getParamName();

    if (strcmp(param_name, "Power") == 0) {
        Serial.printf("Received value = %s for %s - %s\n",
                      val.val.b ? "true" : "false", device_name, param_name);
        switch_state = val.val.b;
        (switch_state == false) ? digitalWrite(gpio_switch, LOW)
        : digitalWrite(gpio_switch, HIGH);
        param->updateAndReport(val);
    }
}

void setup()
{
    Serial.begin(115200);
    pinMode(gpio_0, INPUT);
    pinMode(gpio_switch, OUTPUT);
    digitalWrite(gpio_switch, DEFAULT_POWER_MODE);

    Node my_node;
    my_node = RMaker.initNode("ESP RainMaker Node");

    // Initialize switch device
    my_switch = new Switch("Switch", &gpio_switch);
    if (!my_switch) {
        return;
    }
    // Standard switch device
    my_switch->addCb(write_callback);

    // Add switch device to the node
    my_node.addDevice(*my_switch);

    // This is optional
    RMaker.enableOTA(OTA_USING_TOPICS);
    // If you want to enable scheduling, set time zone for your region using
    // setTimeZone(). The list of available values are provided here
    // https://rainmaker.espressif.com/docs/time-service.html
    //  RMaker.setTimeZone("Asia/Shanghai");
    //  Alternatively, enable the Timezone service and let the phone apps set the
    //  appropriate timezone
    RMaker.enableTZService();

    RMaker.enableSchedule();

    RMaker.enableScenes();
    // Enable ESP Insights. Insteads of using the default http transport, this function will
    // reuse the existing MQTT connection of Rainmaker, thereby saving memory space.
    initAppInsights();

    RMaker.enableSystemService(SYSTEM_SERV_FLAGS_ALL, 2, 2, 2);

    RMaker.start();

    WiFi.onEvent(sysProvEvent);
#if CONFIG_IDF_TARGET_ESP32S2
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE,
                            WIFI_PROV_SECURITY_1, pop, service_name);
#else
    WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM,
                            WIFI_PROV_SECURITY_1, pop, service_name);
#endif
}

void loop()
{
    if (digitalRead(gpio_0) == LOW) {  // Push button pressed

        // Key debounce handling
        delay(100);
        int startTime = millis();
        while (digitalRead(gpio_0) == LOW) {
            delay(50);
        }
        int endTime = millis();

        if ((endTime - startTime) > 10000) {
            // If key pressed for more than 10secs, reset all
            Serial.printf("Reset to factory.\n");
            RMakerFactoryReset(2);
        } else if ((endTime - startTime) > 3000) {
            Serial.printf("Reset Wi-Fi.\n");
            // If key pressed for more than 3secs, but less than 10, reset Wi-Fi
            RMakerWiFiReset(2);
        } else {
            // Toggle device state
            switch_state = !switch_state;
            Serial.printf("Toggle State to %s.\n", switch_state ? "true" : "false");
            if (my_switch) {
                my_switch->updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME,
                                                switch_state);
            }
            (switch_state == false) ? digitalWrite(gpio_switch, LOW)
            : digitalWrite(gpio_switch, HIGH);
        }
    }
    delay(100);
}

My environment:
Windows 11
VSCode 1.81.1
PlatformIO: Core 6.1.10·Home 3.4.4
Espressif 32 Platform 5.2.0
Board: DOIT ESP32 DEVKIT V1

Hi Ivan, I was in contact with the Espressif engineers. They told me that the Espressif Arduino Team only supports ESP32 on the Arduino IDE. PlatformIO support for ESP32 is done and supported by the PlatformIO team which maintains all the tools, binary blobs, packages, and scripts, while Espressif just supplies the releases to you. As such, they can’t support me in exploring utilizing Rainmaker with VSCode and PlatformIO. I will highly appreciate your help in resolving this as I am sure that I am not the only one looking for a solution. Thanks a lot!

Do you use the same ESP32 Core for Arduino? See PlatformIO Registry

See also Release 5.2.0 · platformio/platform-espressif32 · GitHub

And

https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform.html

On Arduino IDE, I installed the esp32 board support package coming from Espressif. Looking at the version, it is 2.0.11

Hello, Any update on that?

Hello, Any help in developing for ESP Rainmaker will be highly appreciated!
If there is no solution I will switch to the Arduino IDE as it works with that.
Thanks!