espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.3k stars 7.35k forks source link

esp rainmaker and esp32c3 #10119

Open hasan12977 opened 1 month ago

hasan12977 commented 1 month ago

Board

ESP32C3

Device Description

[ 92f1e8e2fcc888726ff7838dad725dd94f43438d_2_690x301 ]

Hardware Configuration

no

Version

v3.0.4

IDE Name

arduino

Operating System

macos 14.5 (23F79)

Flash frequency

80

PSRAM enabled

no

Upload speed

921600

Description

the esp rainmker example codes dont work propperly. after uploading the codes with rainmaker 4Mb no ota partition, it uploads the code but gives this error. in order to connect it to wifi, I have to hold the reset button for more than 3 seconds to initialize the esp rainmmaker, otherwise it does not initialize and fails. the failing part is 'failed to start STA!'. Screenshot 2024-08-05 at 10 30 52 PM

after I manually reset the code using reset button, it gives me the qr code and let me connect to it. while connecting the esp to wifi and confirming, I get these error that sound like something did not work right. WhatsApp Image 2024-08-05 at 22 46 00 Screenshot 2024-08-05 at 10 17 38 PM

after the device is added to esp rainmaker app, If I disconnect and reconnect the esp32, I get the same error I got in the beginning. so basically, esp rainmaker is not usable at the moment.

on the other side, when I used esp idf examples of esp rainmaker, I would get the qr code after uploading the code and the process would go seemless. and after discoonecting and reconnecting, the esp32c3 would reconnect to wifi with no problem.

Sketch

// 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 || CONFIG_IDF_TARGET_ESP32C6
static int gpio_0 = 9;
static int gpio_switch = 8;
#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;

// WARNING: sysProvEvent is called from a separate FreeRTOS task (thread)!
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);  // Will call sysProvEvent() from another thread.
#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);
}

Debug Message

[   397][I][WiFiProv.cpp:163] beginProvision(): Attempting conne[  1458][E][STA.cpp:302] begin(): Failed to start STA!
[   377][I][RMaker.cpp:17] event_handler(): RainMaker Initialize[  1447][E][STA.cpp:302] begin(): Failed to start STA!
[  1513][E][STA.cpp:302] begin(): Failed to start STA!
[   378][I][RMaker.cpp:17] event_handler(): RainMaker Initialize[  1511][E][STA.cpp:302] begin(): Failed to start STA!
[   371][I][RMaker.cpp:17] event_handler(): RainMaker Initialize[  1442][E][STA.cpp:302] begin(): Failed to start STA!
[   377][I][RMaker.cpp:17] event_handler(): RainMaker Initialize[  1460][E][STA.cpp:302] begin(): Failed to start STA!
[   399][I][WiFiProv.cpp:163] beginProvision(): Attempting conne[  1494][E][STA.cpp:302] begin(): Failed to start STA!
[   399][I][WiFiProv.cpp:163] beginProvision(): Attempting conne[  1455][E][STA.cpp:302] begin(): Failed to start STA!

this is when esp rainmaker app is adding the device successfully.

E (24924) security1: Key mismatch. Close connection

(24924) security1: Session setup error -1

(24925) protocomm_ble: Invalid content received, killing connection

(65779) esp-x509-crt-bundle: PK verify failed with error FFFFBD70

E (65780) esp-x509-crt-bundle: Failed to verify certificate

E (67830) esp-tls-mbedtls: mbedtls_ss_handshake returned -0x3000

E (67830) esp-tls: Failed to open new connection

E (67830) transport_base: Failed to open a new connection

(67835) mqtt_client: Error transport connect

E (67838) esp_mqtt_glue: MQTT_EVENT_ERROR

I 843201[I [RMaker. cpp:211 event_handler(): Unhandled RainMaker Event:

Other Steps to Reproduce

please try esp idf rainmaker example and compare it to this one. you will see that many thing is different, even the texts from the core debug info is different than the one in arduino.

I have checked existing issues, online documentation and the Troubleshooting Guide

P-R-O-C-H-Y commented 1 month ago

Hi @hasan12977, thank you for nice report. I have tested the esp32c3 with the RainMaker Switch example, and I did get the same errors:

E (75427) esp-x509-crt-bundle: PK verify failed with error FFFFBD70
E (75428) esp-x509-crt-bundle: Failed to verify certificate
E (75429) esp-tls-mbedtls: mbedtls_ssl_handshake returned -0x3000
E (75434) esp-tls: Failed to open new connection
E (75438) transport_base: Failed to open a new connection
E (75444) mqtt_client: Error transport connect
E (75447) esp_mqtt_glue: MQTT_EVENT_ERROR

How ever, the switch is working normally, so if toggle the switch in APP I am receiving the messages:

Received value = false for Switch - Power
Received value = true for Switch - Power

And also if I toggle the switch with the button on the board, the state is updated in the RainMaker app.

Is your code not working at all or it's working even though you got those errors. Thanks

hasan12977 commented 1 month ago

Hello.

I did not say that there is something wrong with the functionality of the code, ie the switch itself. The issue is that in the beginning, right after uploading the code to esp32c3, the QR code should be printed but it is not. I get the error I mentioned above, the first error. In order to initialize the esp rainmaker, I would need to hold the reset button for more than 3 seconds. Then I can see QR code and BLE provision would work. Then I would get the same errors as you got while adding the device to rainmaker app. Switching the button on and off would work fine. But if I click on reset button or power off and on the esp32c3, I would get the same errors as I got in the beginning, ie the first error.

I forgot to mention but I have three esp32c3 super mini that I am testing the code with and all shows the same errors. I don't think there is any problem with regular esp32, and I kind of want to get rid of esp32c3 because I basically can't get them work the way I want. I mainly wanted to use these for low power applications but seems like it is easier and more reliable to use regular esp32. I am pretty sure these issues have something to do with RISC V architecture and development process.

P-R-O-C-H-Y commented 1 month ago

Hi @hasan12977, I am currently investigating this issue.

The QR code is shown only if the device is on factory reset or WiFi reset. If you have your board already added in the RainMaker, and you just flashed new firmware, it will connect again to the same wifi, no need for QR code. But there is an issue, that its not connecting again, failing to start WiFI STA.

With this workaround I made it to work. Can you please test it on your end? in arduino-esp32/libraries/WiFi/src/STA.cpp on line 296 replace the STAClass::begin function with this one:

bool STAClass::begin(bool tryConnect) {
  if (!WiFi.enableSTA(true)) {
    log_e("STA enable failed!");
    return false;
  }
  if (!waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) {
    log_e("NETIF_STARTED_BIT not set! try to connect anyway...");
  }
  if (tryConnect) {
    return connect();
  }
  return true;
}

With this workaround this error will get printed: [ 2036][E][STA.cpp:302] begin(): NETIF_STARTED_BIT not set! try to connect anyway... But the board will reconnect to WiFi and RainMaker will continue working.

To see the QR code you would need to do one of the following:

  1. Set in the Tools menu of Arduino IDE: Erase all flash after upload -> Enabled. By that the old WiFi credentials gets removed and you should be able to see the QR code every time you upload new firmware
  2. Hold boot button for 3 seconds to reset WiFi (as you already was doing)
  3. Hold boot for more than 10 seconds to factory reset the board

The other errors that gets printed I am discussing with the RainMaker team.

P-R-O-C-H-Y commented 1 month ago

One more thing, as you are not using OTA -> used partition without OTA. You should comment/remove RMaker.enableOTA(OTA_USING_TOPICS); function in the code. By that you will also get rid of first 2 errors that gets printed.

fmb787 commented 1 month ago

Hi @P-R-O-C-H-Y i faced one of above issue which is ESP32 will not connect to wifi after its restart/power off

i follow your workaround "mentioned above" and it works .


18:40:57.508 -> https://rainmaker.espressif.com/qrcode.html?data={"ver":"v1","name":"PROV_1234","pop":"12345678","transport":"ble"}
18:41:30.259 -> [ 40723][I][RMaker.cpp:19] event_handler(): RainMaker Claim Successful.
18:41:45.262 -> E (55721) esp-tls-mbedtls: mbedtls_ssl_setup returned -0x7F00
18:41:45.262 -> E (55722) esp-tls: create_ssl_handle failed
18:41:45.262 -> E (55722) esp-tls: Failed to open new connection
18:41:45.262 -> E (55724) transport_base: Failed to open a new connection
18:41:45.262 -> E (55730) mqtt_client: Error transport connect
18:41:45.262 -> E (55733) esp_mqtt_glue: MQTT_EVENT_ERROR
18:41:55.989 -> E (79686) wifi_prov_scheme_ble: bt_mem_release of BTDM failed 259
18:42:04.353 -> [ 74859][I][RMaker.cpp:21] event_handler(): Unhandled RainMaker Event:
18:42:19.647 -> Received value = false for Switch - Power
18:42:22.680 -> Received value = true for Switch - Power

i tested it from app the i clicked (Reboot ) from app

18:42:38.435 -> E (122123) wifi:NAN WiFi stop
18:42:38.435 -> E (122126) transport_base: poll_read select error 113, errno = Software caused connection abort, fd = 48
18:42:38.435 -> E (122126) mqtt_client: Poll read error: 119, aborting connection
18:42:38.435 -> ets Jul 29 2019 12:21:46
18:42:38.435 -> 
18:42:38.435 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
18:42:38.494 -> configsip: 0, SPIWP:0xee
18:42:38.494 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
18:42:38.494 -> mode:DIO, clock div:1
18:42:38.494 -> load:0x3fff0030,len:4832
18:42:38.494 -> load:0x40078000,len:16460
18:42:38.494 -> load:0x40080400,len:4
18:42:38.494 -> load:0x40080404,len:3504
18:42:38.494 -> entry 0x400805cc
18:42:39.216 -> [    85][I][RMaker.cpp:17] event_handler(): RainMaker Initialized.
18:42:39.216 -> [   101][I][WiFiProv.cpp:159] beginProvision(): Already Provisioned
18:42:39.216 -> [   108][I][WiFiProv.cpp:163] beginProvision(): Attempting connect to AP: xxxxxxx
18:42:39.217 -> 
18:42:39.310 -> E (188) wifi_prov_scheme_ble: bt_mem_release of BTDM failed 259
18:42:40.301 -> [  1193][E][STA.cpp:302] begin(): NETIF_STARTED_BIT not set! try to connect anyway...
18:43:00.776 -> Received value = false for Switch - Power
18:43:02.343 -> Received value = true for Switch - Power`
hasan12977 commented 4 weeks ago

yes, the workaround works and gives the errors that you mentioned. it does reconnect after I restart the esp32c3 super minis. but I prefer to have these in my serial monitor:

Screenshot 2024-08-08 at 5 43 12 PM

so I can see what is happening in the background.

this is from esp idf example. this is what happens when I restart the esp32c3. I used temperture sensor example from esp idf rather than arduino:

Screenshot 2024-08-12 at 10 34 17 PM

also, as you can see OTA works too. but I dont have that option in arduino. only 4mb and 4mb without ota. when I choose rainmaker 4mb, it gives error saying the program is bigger than 2 mb.

P-R-O-C-H-Y commented 4 weeks ago

yes, the workaround works and gives the errors that you mentioned. it does reconnect after I restart the esp32c3 super minis. but I prefer to have these in my serial monitor:

Screenshot 2024-08-08 at 5 43 12 PM

so I can see what is happening in the background.

this is from esp idf example. this is what happens when I restart the esp32c3. I used temperture sensor example from esp idf rather than arduino:

Screenshot 2024-08-12 at 10 34 17 PM

also, as you can see OTA works too. but I dont have that option in arduino. only 4mb and 4mb without ota. when I choose rainmaker 4mb, it gives error saying the program is bigger than 2 mb.

Our binary is quite bigger as we use BlueDroid as the BLE lib. In IDF the default one is NimBLE, which is taking less space. We plan to switch over the NimBLE in future to make the binaries smaller. That's why you are not able to use the OTA on 4MB chips when using BLE provisioning.

I am already discussing the errors with the RainMaker team.