I am using LwIP library in order to create an MQTT connection with a broker. The client, which I am programming is connected to the broker successfully and I can read messages also. Nonetheless, when I am trying to send a JSON message with the MQTT-Explorer I can't read it. Let me explain a little bit more. I have a callback function which is named as static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags). The data from MQTT-Explorer is stored into the variable *const u8_t data and I converting it into a proper char *json_data value in order to manipulate it in another function, which takes the json_data and parsing it with the cJSON library. The issue here is that the json = cJSON_Parse(json_string); returns NULL. I think that the problem is the way I am converting it to char. I am writing the program to the STM32CubeIDE 1.13.2. Let me know if you can figure out what is the problem with the NULL return in cJSON_Parse(json_string).
In the code below I have used a dummy method for debug, with queue and MVP model, because I am working with graphics in STM32H7 microcontroller and Riverdi screen.
Here is the code from the callback function where lets say I am converting u8_t to char and calling the extract_data function where the issue is.
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
{
//char *json_data = (char *) data; First try of conversion.
char json_data[len+1];
memcpy(json_data, data, len);
if (flag0.fl.f0)
{
extract_data(json_data); // Send the valid data of topology topic for data extraction.
while (flag0.fl.f0) {} // Wait until the data extraction successfully finished.
if (osMessageQueueGetSpace(TaskQueueHandle)>0)
{
osMessageQueuePut(TaskQueueHandle, &topics_data_s, 0, 0); // Send data to the screen via the queue.
}
}else if (flag0.fl.f1)
{
if (osMessageQueueGetSpace(DataQueueHandle)>0)
{
osMessageQueuePut(DataQueueHandle, json_data, 0, 0); // Send data to the screen via the queue.
}
}
}
Here is the function that shows the issue:
void extract_data(const char *json_string) {
cJSON *json;
json = cJSON_Parse(json_string); // Parsing string contents, in order to convert it as JSON format.
if (json == NULL) // Error in parsing data.
{
**THE CODE IS GETTING HERE WHEN I AM CALLING THE FUNCTION.**
// Just a dummy message.
if (osMessageQueueGetSpace(DataQueueHandle)>0)
{
osMessageQueuePut(DataQueueHandle, "m", 0, 0); // Send data to the screen via the queue.
}
printf("Error in parsing JSON data!\n\r");
}else if (json != NULL) // Parsing data was successfully done.
{
cJSON *controllers = cJSON_GetObjectItemCaseSensitive(json, "controllers"); // From JSON format get the contents of array "controllers".
if (cJSON_IsArray(controllers)){
cJSON *controller1 = cJSON_GetArrayItem(controllers, 0); // Store to controller1 the first item of the array, which are those two contents " device_uid:...., position:......", left side.
cJSON *controller2 = cJSON_GetArrayItem(controllers, 1); // Store to controller2 the second item of the array, which are those two contents " device_uid:...., position:.....", right side
cJSON *device_uid_1 = cJSON_GetObjectItemCaseSensitive(controller1, "device_uid"); // Extract the data of device_uid, which its position value is equal to one("1").
cJSON *device_uid_2 = cJSON_GetObjectItemCaseSensitive(controller2, "device_uid"); // Extract the data of device_uid, which its position value is equal to two("2").
/* Check if device_uid data is valid and up to date */
if (cJSON_IsString(device_uid_1)) // For left device.
{
strcpy(topics_data_s.left_uid, device_uid_1->valuestring); // Store the content of device_uid to left parameter, in order to specify the left socket UID.
}
if (cJSON_IsString(device_uid_2)) // For right device
{
strcpy(topics_data_s.right_uid, device_uid_2->valuestring); // Store the content of device_uid to right parameter, in order to specify the right socket UID.
}
}
cJSON_Delete(json); // Finish with the JSON parser and close it.
flag0.fl.f0=0; // This flag when it is equal to 0, means that the UID identification was successfully done and the back end can send the data to the queue.
}
}
I had tried the above code example in order to manipulate the MQTT incoming message as a JSON because it has a lot of useful information that I need to extract, but it return NULL. Nonetheless, the other messages are appearing properly to the screen when I use publish method via MQTT-Explorer. The data that I am publishing thought MQTT-Explorer is that with this form:
[
{
"parent_uid": "d0a13a",
"position": 1,
"controllers": [
{
"parent_device_uid": "d0a13a",
"device_uid": "018660",
"position": 1
},
{
"parent_device_uid": "d0a13a",
"device_uid": "013523",
"position": 2
}
]
}
]
As per the comments; cJSON_Parse
is expecting a null terminated string. However
char json_data[len+1];
memcpy(json_data, data, len);
Does not deliver this; the value of json_data[len]
is indeterminate; C does not initialise arrays to 0 (well it does in some cases) and the memcpy
copies data into json_data[0]
to json_data[len-1]
so nothing is written to json_data[len]
(the source is an array for which you are provided a length, meaning it's most likely not null terminated).
The easy fix is to add the null with json_data[len] = '\0';
.