Page 1 of 1

Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 4:21 am
by senudajayalath
I have compiled and run the example code which written in C and it works perfectly. But now I want to integrate that example(Written in C) to my main code which is in C++. I made couple of changes where I replaced malloc keyword with new keyword and I compiled it. It compiles successfully but when I flash the code espnow_send does not work. This is the function where the problem is at,

Code: Select all

extern "C" void example_espnow_task(void *pvParameter)
{
  example_espnow_event_t evt;
  uint8_t recv_state = 0;
  uint16_t recv_seq = 0;
  int recv_magic = 0;
  bool is_broadcast = false;
  int ret;

  vTaskDelay(5000 / portTICK_RATE_MS);
  ESP_LOGI(TAG, "Start sending broadcast data");

  /* Start sending broadcast ESPNOW data. */
  example_espnow_send_param_t *send_param = (example_espnow_send_param_t *)pvParameter;
  ESP_LOGI(TAG, "MAC : %d", esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len));
  
  if (esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len) != ESP_OK)
  {
    ESP_LOGE(TAG, "Send error");
    example_espnow_deinit(send_param);
    vTaskDelete(NULL);
  }

  while (xQueueReceive(s_example_espnow_queue, &evt, portMAX_DELAY) == pdTRUE)
  {
    switch (evt.id)
    {
    case EXAMPLE_ESPNOW_SEND_CB:
    {
      example_espnow_event_send_cb_t *send_cb = &evt.info.send_cb;
      is_broadcast = IS_BROADCAST_ADDR(send_cb->mac_addr);

      ESP_LOGD(TAG, "Send data to " MACSTR ", status1: %d", MAC2STR(send_cb->mac_addr), send_cb->status);

      if (is_broadcast && (send_param->broadcast == false))
      {
        break;
      }

      if (!is_broadcast)
      {
        send_param->count--;
        if (send_param->count == 0)
        {
          ESP_LOGI(TAG, "Send done");
          example_espnow_deinit(send_param);
          vTaskDelete(NULL);
        }
      }

      /* Delay a while before sending the next data. */
      if (send_param->delay > 0)
      {
        vTaskDelay(send_param->delay / portTICK_RATE_MS);
      }

      ESP_LOGI(TAG, "send data to " MACSTR "", MAC2STR(send_cb->mac_addr));

      memcpy(send_param->dest_mac, send_cb->mac_addr, ESP_NOW_ETH_ALEN);
      example_espnow_data_prepare(send_param);

      /* Send the next data after the previous data is sent. */
      if (esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len) != ESP_OK)
      {
        ESP_LOGE(TAG, "Send error");
        example_espnow_deinit(send_param);
        vTaskDelete(NULL);
      }
      break;
    }
    case EXAMPLE_ESPNOW_RECV_CB:
    {
      example_espnow_event_recv_cb_t *recv_cb = &evt.info.recv_cb;

      ret = example_espnow_data_parse(recv_cb->data, recv_cb->data_len, &recv_state, &recv_seq, &recv_magic);

      free(recv_cb->data);
      if (ret == EXAMPLE_ESPNOW_DATA_BROADCAST)
      {
        ESP_LOGI(TAG, "Receive %dth broadcast data from: " MACSTR ", len: %d", recv_seq, MAC2STR(recv_cb->mac_addr), recv_cb->data_len);

        /* If MAC address does not exist in peer list, add it to peer list. */
        if (esp_now_is_peer_exist(recv_cb->mac_addr) == false)
        {
          esp_now_peer_info_t *peer = new esp_now_peer_info_t[sizeof(esp_now_peer_info_t)];
          if (peer == NULL)
          {
            ESP_LOGE(TAG, "Malloc peer information fail");
            example_espnow_deinit(send_param);
            vTaskDelete(NULL);
          }
          memset(peer, 0, sizeof(esp_now_peer_info_t));
          peer->channel = CONFIG_ESPNOW_CHANNEL;
          peer->ifidx = ESPNOW_WIFI_IF;
          peer->encrypt = true;
          memcpy(peer->lmk, CONFIG_ESPNOW_LMK, ESP_NOW_KEY_LEN);
          memcpy(peer->peer_addr, recv_cb->mac_addr, ESP_NOW_ETH_ALEN);
          ESP_ERROR_CHECK(esp_now_add_peer(peer));
          free(peer);
        }

        /* Indicates that the device has received broadcast ESPNOW data. */
        if (send_param->state == 0)
        {
          send_param->state = 1;
        }
      }
      else if (ret == EXAMPLE_ESPNOW_DATA_UNICAST)
      {
        ESP_LOGI(TAG, "Receive %dth unicast data from: " MACSTR ", len: %d", recv_seq, MAC2STR(recv_cb->mac_addr), recv_cb->data_len);

        /* If receive unicast ESPNOW data, also stop sending broadcast ESPNOW data. */
        send_param->broadcast = false;
      }
      else
      {
        ESP_LOGI(TAG, "Receive error data from: " MACSTR "", MAC2STR(recv_cb->mac_addr));
      }
      break;
    }
    default:
      ESP_LOGE(TAG, "Callback type error: %d", evt.id);
      break;
    }
  }
}

After seeing the terminal output it appeared to me that the error was in

Code: Select all

esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len)
where it did not return a ESP_OK. Can anyone help me understand why this error is given and how to overcome this. The whole code is attached as an attachment below
This is the error printed on the terminal,

E (5897) espnow_example: Send error

Thanks

Re: Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 4:48 am
by ESP_Sprite
Not without seeing a. the error code, and b, the rest of the code.

Re: Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 5:00 am
by boarchuz
senudajayalath wrote:
Fri Oct 29, 2021 4:21 am

Code: Select all

  ESP_LOGI(TAG, "MAC : %d", esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len));
Likely culprit here

Re: Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 11:08 am
by senudajayalath
ESP_Sprite wrote:
Fri Oct 29, 2021 4:48 am
Not without seeing a. the error code, and b, the rest of the code.
I have attached the whole code and also updated my question with the error. Please take a look. Thanks

Re: Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 11:14 am
by senudajayalath
boarchuz wrote:
Fri Oct 29, 2021 5:00 am
senudajayalath wrote:
Fri Oct 29, 2021 4:21 am

Code: Select all

  ESP_LOGI(TAG, "MAC : %d", esp_now_send(send_param->dest_mac, send_param->buffer, send_param->len));
This just prints, I (5887) espnow_example: MAC : 12396. So I'm assuming there is an error whencalling esp_now-send because ideally this should return 0
Likely culprit here

Re: Problems with converting espnow code to C++

Posted: Fri Oct 29, 2021 1:28 pm
by boarchuz
example_espnow_init:

Code: Select all

esp_now_peer_info_t *peer = new esp_now_peer_info_t[sizeof(esp_now_peer_info_t)];
send_param = new example_espnow_send_param_t[sizeof(example_espnow_send_param_t)];
I don't think your intention is to allocate arrays of these objects.

Code: Select all

send_param->buffer = new uint8_t(13);
I try to avoid C++ but I understand this allocates memory for a uint8_t and initialises it to 13. It doesn't allocate 13 bytes.

example_espnow_data_prepare:

Code: Select all

example_espnow_data_t *buf = (example_espnow_data_t *)send_param->buffer;
You then dereference the above uint8_t* and write a bunch of stuff to memory you don't own, corrupting the heap.

Re: Problems with converting espnow code to C++

Posted: Sat Oct 30, 2021 9:53 am
by senudajayalath
I reworked on the main.cpp. I have attached the modified file below. But it still gives the same error of ,

"espnow_example: Send error".

Any other tip? Much appreciated.