MQTT PPP connection to Thingsboard

Palonso
Posts: 95
Joined: Tue Sep 24, 2019 8:43 pm

MQTT PPP connection to Thingsboard

Postby Palonso » Mon Oct 07, 2019 8:13 pm

Hi,

I'm trying to send some MQTT packets to thingsboard.io using the pppos_client example provided on ESP-IDF Github but I have the next output:

Code: Select all

I (0) cpu_start: App cpu up.
I (375) heap_init: Initializing. RAM available for dynamic allocation:
I (382) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (388) heap_init: At 3FFB4430 len 0002BBD0 (174 KiB): DRAM
I (394) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (400) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (407) heap_init: At 4008AF64 len 0001509C (84 KiB): IRAM
I (413) cpu_start: Pro cpu start user code
I (431) spi_flash: detected chip: generic
I (432) spi_flash: flash io: dio
I (432) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (442) uart: queue free spaces: 30
I (1602) pppos_example: Module: BG96
I (1602) pppos_example: Operator: "$OPERATOR_NAME"
I (1602) pppos_example: IMEI: $valid_imei
I (1602) pppos_example: IMSI: $valid_imsi
I (1802) pppos_example: rssi: 31, ber: 99
I (2002) pppos_example: Battery voltage: 3633 mV
I (2202) pppos_example: Modem PPP Started
I (3402) pppos_example: Modem Connect to PPP Server
I (3402) pppos_example: ~~~~~~~~~~~~~~
I (3402) pppos_example: IP          : $valid_number_1
I (3402) pppos_example: Netmask     : 255.255.255.255
I (3412) pppos_example: Gateway     : $valid_number_2
I (3412) pppos_example: Name Server1: $valid_number_3
I (3422) pppos_example: Name Server2: $valid_number_4
I (3422) pppos_example: ~~~~~~~~~~~~~~
I (3432) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (3442) pppos_example: MQTT other event id: 7
I (4292) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
W (4802) MQTT_CLIENT: Connection refused, bad username or password
I (4802) MQTT_CLIENT: Error MQTT Connected
I (4802) pppos_example: MQTT_EVENT_DISCONNECTED
My problem is that I don't have any user or password to send in order to connect, on the other hand I used the command prompt using the next command:

Code: Select all

curl -v -X POST -d "{\"temperature\": 25}" https://demo.thingsboard.io/api/v1/$ACCESS_TOKEN/telemetry --header "Content-Type:application/json"
And I recieved that testing package on the thingsboard page.

PS: I'm adding the code I'm using but mostly is the same code as in the example

Code: Select all

/* PPPoS Client Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "tcpip_adapter.h"
#include "mqtt_client.h"
#include "esp_modem.h"
#include "esp_log.h"
#include "sim800.h"
#include "bg96.h"

#define BROKER_URL "mqtt://demo.thingsboard.io/api/v1/$ACCESS_TOKEN/telemetry"

static const char *TAG = "pppos_example";
static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0;
static const int STOP_BIT = BIT1;
static const int GOT_DATA_BIT = BIT2;

//----------------------------SMS CONFIGURATIONS--------------------------------
#if CONFIG_EXAMPLE_SEND_MSG
/**
 * @brief This example will also show how to send short message using the infrastructure provided by esp modem library.
 * @note Not all modem support SMG.
 *
 */
static esp_err_t example_default_handle(modem_dce_t *dce, const char *line)
{
    esp_err_t err = ESP_FAIL;
    if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
        err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
    } else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
        err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
    }
    return err;
}

static esp_err_t example_handle_cmgs(modem_dce_t *dce, const char *line)
{
    esp_err_t err = ESP_FAIL;
    if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
        err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
    } else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
        err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
    } else if (!strncmp(line, "+CMGS", strlen("+CMGS"))) {
        err = ESP_OK;
    }
    return err;
}

#define MODEM_SMS_MAX_LENGTH (128)
#define MODEM_COMMAND_TIMEOUT_SMS_MS (120000)
#define MODEM_PROMPT_TIMEOUT_MS (10)

static esp_err_t example_send_message_text(modem_dce_t *dce, const char *phone_num, const char *text)
{
    modem_dte_t *dte = dce->dte;
    dce->handle_line = example_default_handle;
    /* Set text mode */
    if (dte->send_cmd(dte, "AT+CMGF=1\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
        ESP_LOGE(TAG, "send command failed");
        goto err;
    }
    if (dce->state != MODEM_STATE_SUCCESS) {
        ESP_LOGE(TAG, "set message format failed");
        goto err;
    }
    ESP_LOGD(TAG, "set message format ok");
    /* Specify character set */
    dce->handle_line = example_default_handle;
    if (dte->send_cmd(dte, "AT+CSCS=\"GSM\"\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
        ESP_LOGE(TAG, "send command failed");
        goto err;
    }
    if (dce->state != MODEM_STATE_SUCCESS) {
        ESP_LOGE(TAG, "set character set failed");
        goto err;
    }
    ESP_LOGD(TAG, "set character set ok");
    /* send message */
    char command[MODEM_SMS_MAX_LENGTH] = {0};
    int length = snprintf(command, MODEM_SMS_MAX_LENGTH, "AT+CMGS=\"%s\"\r", phone_num);
    /* set phone number and wait for "> " */
    dte->send_wait(dte, command, length, "\r\n> ", MODEM_PROMPT_TIMEOUT_MS);
    /* end with CTRL+Z */
    snprintf(command, MODEM_SMS_MAX_LENGTH, "%s\x1A", text);
    dce->handle_line = example_handle_cmgs;
    if (dte->send_cmd(dte, command, MODEM_COMMAND_TIMEOUT_SMS_MS) != ESP_OK) {
        ESP_LOGE(TAG, "send command failed");
        goto err;
    }
    if (dce->state != MODEM_STATE_SUCCESS) {
        ESP_LOGE(TAG, "send message failed");
        goto err;
    }
    ESP_LOGD(TAG, "send message ok");
    return ESP_OK;
err:
    return ESP_FAIL;
}
#endif
//------------------------------------------------------------------------------

static void modem_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    switch (event_id) {
    case MODEM_EVENT_PPP_START:
        ESP_LOGI(TAG, "Modem PPP Started");
        break;
    case MODEM_EVENT_PPP_CONNECT:
        ESP_LOGI(TAG, "Modem Connect to PPP Server");
        ppp_client_ip_info_t *ipinfo = (ppp_client_ip_info_t *)(event_data);
        ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
        ESP_LOGI(TAG, "IP          : " IPSTR, IP2STR(&ipinfo->ip));
        ESP_LOGI(TAG, "Netmask     : " IPSTR, IP2STR(&ipinfo->netmask));
        ESP_LOGI(TAG, "Gateway     : " IPSTR, IP2STR(&ipinfo->gw));
        ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&ipinfo->ns1));
        ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&ipinfo->ns2));
        ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
        xEventGroupSetBits(event_group, CONNECT_BIT);
        break;
    case MODEM_EVENT_PPP_DISCONNECT:
        ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
        break;
    case MODEM_EVENT_PPP_STOP:
        ESP_LOGI(TAG, "Modem PPP Stopped");
        xEventGroupSetBits(event_group, STOP_BIT);
        break;
    case MODEM_EVENT_UNKNOWN:
        ESP_LOGW(TAG, "Unknow line received: %s", (char *)event_data);
        break;
    default:
        break;
    }
}

static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch (event->event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        msg_id = esp_mqtt_client_subscribe(client, "/telemetry", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        msg_id = esp_mqtt_client_publish(client, "/telemetry", "esp32-pppos", 0, 0, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        xEventGroupSetBits(event_group, GOT_DATA_BIT);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "MQTT other event id: %d", event->event_id);
        break;
    }
    return ESP_OK;
}

void app_main(void)
{
    tcpip_adapter_init();
    event_group = xEventGroupCreate();
    
    /* create dte object */
    esp_modem_dte_config_t config = ESP_MODEM_DTE_DEFAULT_CONFIG();
    modem_dte_t *dte = esp_modem_dte_init(&config);
   
    /* Register event handler */
    ESP_ERROR_CHECK(esp_modem_add_event_handler(dte, modem_event_handler, NULL));
   
    /* create dce object */
    modem_dce_t *dce = bg96_init(dte);
    ESP_ERROR_CHECK(dce->set_flow_ctrl(dce, MODEM_FLOW_CONTROL_NONE));
    ESP_ERROR_CHECK(dce->store_profile(dce));
    
    /* Print Module ID, Operator, IMEI, IMSI */
    ESP_LOGI(TAG, "Module: %s", dce->name);
    ESP_LOGI(TAG, "Operator: %s", dce->oper);
    ESP_LOGI(TAG, "IMEI: %s", dce->imei);
    ESP_LOGI(TAG, "IMSI: %s", dce->imsi);
    
    /* Get signal quality */
    uint32_t rssi = 0, ber = 0;
    ESP_ERROR_CHECK(dce->get_signal_quality(dce, &rssi, &ber));
    ESP_LOGI(TAG, "rssi: %d, ber: %d", rssi, ber);
   
    /* Get battery voltage */
    uint32_t voltage = 0, bcs = 0, bcl = 0;
    ESP_ERROR_CHECK(dce->get_battery_status(dce, &bcs, &bcl, &voltage));
    ESP_LOGI(TAG, "Battery voltage: %d mV", voltage);

    /* Setup PPP environment */
    esp_modem_setup_ppp(dte);

    /* Wait for IP address */
    xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);

    /* Config MQTT */
    esp_mqtt_client_config_t mqtt_config = {
        .uri = BROKER_URL,
        .event_handle = mqtt_event_handler,
    };

    esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
    esp_mqtt_client_start(mqtt_client);
    xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
    esp_mqtt_client_destroy(mqtt_client);

    /* Exit PPP mode */
    ESP_ERROR_CHECK(esp_modem_exit_ppp(dte));
    xEventGroupWaitBits(event_group, STOP_BIT, pdTRUE, pdTRUE, portMAX_DELAY);

#if CONFIG_EXAMPLE_SEND_MSG
    const char *message = "Welcome to ESP32!";
    ESP_ERROR_CHECK(example_send_message_text(dce, CONFIG_EXAMPLE_SEND_MSG_PEER_PHONE_NUMBER, message));
    ESP_LOGI(TAG, "Send send message [%s] ok", message);
#endif
   
    /* Power down module */
    ESP_ERROR_CHECK(dce->power_down(dce));
    ESP_LOGI(TAG, "Power down");
    ESP_ERROR_CHECK(dce->deinit(dce));
    ESP_ERROR_CHECK(dte->deinit(dte));
}
PS2: I also tried the HiveMQ free dashboard as MQTT broker and I managed to get the message, so I don't know why I can't on thingsboard

UPDATE: I checked the OTA update code provided by Thingsboard people, and discovered that the "username" would be the $ACCESS_TOKEN of the device.

So it would be something like this:

Code: Select all

/* Config MQTT */
    esp_mqtt_client_config_t mqtt_config = {
        .uri = BROKER_URL,
        .event_handle = mqtt_event_handler,
        .username = "$ACCESS_TOKEN",
    };
    
and some small changes on the handler:

Code: Select all

static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch (event->event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        msg_id = esp_mqtt_client_subscribe(client, "/telemetry", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        msg_id = esp_mqtt_client_publish(client, "/telemetry", "esp32-pppos", 0, 0, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        xEventGroupSetBits(event_group, GOT_DATA_BIT);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "MQTT other event id: %d", event->event_id);
        break;
    }
    return ESP_OK;
}
After changing those parts of the code I got this new message:

Code: Select all

/*----------pretty much the same log as before----------*/
I (2202) pppos_example: Modem PPP Started
I (3402) pppos_example: Modem Connect to PPP Server
I (3402) pppos_example: ~~~~~~~~~~~~~~
I (3402) pppos_example: IP          : $valid_number_1
I (3402) pppos_example: Netmask     : 255.255.255.255
I (3412) pppos_example: Gateway     : $valid_number_2
I (3412) pppos_example: Name Server1: $valid_number_3
I (3422) pppos_example: Name Server2: $valid_number_4
I (3422) pppos_example: ~~~~~~~~~~~~~~
I (3432) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (3442) pppos_example: MQTT other event id: 7
I (4662) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
I (5372) pppos_example: MQTT_EVENT_CONNECTED
I (5372) pppos_example: sent subscribe successful, msg_id=22797
E (5762) MQTT_CLIENT: mqtt_message_receive: received a message with an invalid header=0x92
E (5762) MQTT_CLIENT: mqtt_process_receive: mqtt_message_receive() returned -1
I (5762) pppos_example: MQTT_EVENT_DISCONNECTED
/*----------here starts a loop trying to publish----------*/
Trying a similar code of the MQTT but over WiFi, and using Wireshark, I discovered that no MQTT packet is sent so I believe there is a problem with the mqtt_message_receive() or mqtt_process_receive() functions.

I'd be thankful of any idea to try out.

PS: Also checking the OTA update from Thingsboard, they do a previous step before publishing with cJSON objects but i got the same results. Here I leave the code they use:

Code: Select all

cJSON *root = cJSON_CreateObject();
        cJSON_AddNumberToObject(root, "counter", counter);
        char *post_data = cJSON_PrintUnformatted(root);
        esp_mqtt_client_publish(mqtt_client, TB_TELEMETRY_TOPIC, post_data, 0, 1, 0);
        cJSON_Delete(root);
        // Free is intentional, it's client responsibility to free the result of cJSON_Print
        free(post_data);
Last edited by Palonso on Thu Jul 23, 2020 10:44 pm, edited 3 times in total.

Who is online

Users browsing this forum: No registered users and 121 guests