MQTT system data receive handler moved to separate file
This commit is contained in:
parent
f6515c5be8
commit
d6e2375fe1
|
|
@ -11,6 +11,7 @@ idf_component_register(
|
|||
"src/ETHTransport.c"
|
||||
"src/SNTP.c"
|
||||
"src/MQTT.c"
|
||||
"src/MQTTSysHandler.c"
|
||||
"src/OTA.c"
|
||||
"extlibs/jRead.c"
|
||||
"extlibs/jWrite.c"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "mqtt_client.h"
|
||||
|
||||
|
||||
typedef int mqtt_app_err_t;
|
||||
|
||||
#define API_OK 0 /*!< success (no error) */
|
||||
|
|
@ -79,4 +80,6 @@ typedef struct
|
|||
mqtt_client_t* GetMQTTHandlesPool(int idx);
|
||||
QueueHandle_t GetMQTTSendQueue(int idx);
|
||||
|
||||
void ControlDataHandler(char *data, uint32_t len, int idx);
|
||||
|
||||
#endif /* MAIN_INCLUDE_MQTT_H_ */
|
||||
|
|
|
|||
354
src/MQTT.c
354
src/MQTT.c
|
|
@ -21,25 +21,13 @@
|
|||
#include "esp_log.h"
|
||||
#include "Helpers.h"
|
||||
#include "SystemConfiguration.h"
|
||||
#include "jWrite.h"
|
||||
#include "jRead.h"
|
||||
|
||||
#include "NetTransport.h"
|
||||
#include "HTTPServer.h"
|
||||
#include "romfs.h"
|
||||
#include "MQTT.h"
|
||||
|
||||
#define CH_MESSAGE_BUFER_LENTH 32 //size of mqtt queue
|
||||
|
||||
#define MESSAGE_LENGTH 32 //base message length, mainly depended by radio requirements
|
||||
#define MAX_JSON_MESSAGE 256 //max size of mqtt message to publish
|
||||
#define MAX_FILE_PUBLISH 4096 //bufer for mqtt data publish
|
||||
#define MAX_DYNVAR_LENTH 64
|
||||
#define MAX_FILENAME_LENTH 15
|
||||
#define MAX_ERROR_MESSAGE 32
|
||||
#define MAX_ERROR_JSON 256
|
||||
#define MAX_MESSAGE_ID 15
|
||||
|
||||
#define MAX_POST_DATA_LENTH 512
|
||||
#define MQTT_RECONNECT_CHANGE_ADAPTER 3
|
||||
|
||||
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
||||
|
|
@ -53,55 +41,8 @@ uint8_t MQTT2MessagesQueueStorageArea[CH_MESSAGE_BUFER_LENTH * sizeof(DATA_SEND_
|
|||
|
||||
mqtt_client_t mqtt[CONFIG_MQTT_CLIENTS_NUM] = { 0 };
|
||||
|
||||
|
||||
|
||||
const char apiver[] = "2.0";
|
||||
const char tagGet[] = "GET";
|
||||
const char tagPost[] = "POST";
|
||||
|
||||
#define TAG "MQTTApp"
|
||||
|
||||
const char* mqtt_app_err_descr[] = {
|
||||
"Operation OK",
|
||||
"Internal error",
|
||||
"Wrong json format",
|
||||
"Key 'idmess' not found",
|
||||
"Key 'idmess' value too long",
|
||||
"Key 'api' not found",
|
||||
"API version not supported",
|
||||
"Key 'request' not found",
|
||||
"Unsupported HTTP method",
|
||||
"Key 'url' not found",
|
||||
"Key 'url' value too long",
|
||||
"URL not found",
|
||||
"Key 'postdata' not found",
|
||||
"Key 'postdata' too long",
|
||||
"File size too big",
|
||||
"File is empty",
|
||||
"Unknown error"
|
||||
};
|
||||
|
||||
const char* mqtt_app_err_breef[] = {
|
||||
"OK",
|
||||
"INTERNAL_ERR",
|
||||
"WRONG_JSON_ERR",
|
||||
"NO_ID_ERR",
|
||||
"ID_OVERSIZE_ERR",
|
||||
"NO_API_ERR",
|
||||
"VERSION_ERR",
|
||||
"NO_REQUEST_ERR",
|
||||
"UNSUPPORTED_METHOD_ERR",
|
||||
"NO_URL_ERR",
|
||||
"URL_OVERSIZE_ERR",
|
||||
"URL_NOT_FOUND_ERR",
|
||||
"NO_POSTDATA_ERR",
|
||||
"POSTDATA_OVERSIZE_ERR",
|
||||
"FILE_OVERSIZE_ERR",
|
||||
"FILE_EMPTY_ERR",
|
||||
"UNKNOWN_ERR"
|
||||
};
|
||||
|
||||
static void ControlDataHandler(char *data, uint32_t len, int idx);
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
||||
|
||||
mqtt_client_t* GetMQTTHandlesPool(int idx)
|
||||
|
|
@ -187,12 +128,7 @@ static void ComposeTopicScreen(char *topic, char *roottopic, char *ident, uint8_
|
|||
strcat((char*) topic, (const char*) "/SCREEN");
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNSUPPORTED = 0,
|
||||
GET,
|
||||
POST
|
||||
} mqtt_api_request_t;
|
||||
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
|
|
@ -303,289 +239,6 @@ static void reconnect_MQTT_handler(void *arg, esp_event_base_t event_base,
|
|||
}
|
||||
}
|
||||
|
||||
static mqtt_app_err_t ResponceWithError(int idx,
|
||||
espfs_file_t *file,
|
||||
char *id,
|
||||
char *url,
|
||||
mqtt_app_err_t api_err)
|
||||
{
|
||||
espfs_fclose(file);
|
||||
char JSONErrorMess[MAX_ERROR_JSON];
|
||||
jwOpen(JSONErrorMess, MAX_ERROR_JSON, JW_OBJECT, JW_PRETTY);
|
||||
if (id[0])
|
||||
jwObj_string("messid", (char*) id);
|
||||
else
|
||||
jwObj_string("messid", "ERROR");
|
||||
jwObj_string("api", (char*) apiver);
|
||||
jwObj_string("responce", (char*) mqtt_app_err_breef[api_err]);
|
||||
jwObj_string("descript", (char*) mqtt_app_err_descr[api_err]);
|
||||
if (url[0])
|
||||
jwObj_string("url", (char*) url);
|
||||
else
|
||||
jwObj_string("url", "ERROR");
|
||||
jwEnd();
|
||||
jwClose();
|
||||
char *buf = (char*) malloc(strlen(JSONErrorMess) + 1);
|
||||
if (buf)
|
||||
{
|
||||
memcpy(buf, JSONErrorMess, strlen(JSONErrorMess));
|
||||
DATA_SEND_STRUCT DSS;
|
||||
DSS.dt = PUBLISH_CONTROL_DATA;
|
||||
DSS.raw_data_ptr = buf;
|
||||
DSS.data_lenth = strlen(JSONErrorMess);
|
||||
if (xQueueSend(mqtt[idx].mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
||||
return API_OK;
|
||||
else
|
||||
{
|
||||
free(buf);
|
||||
return API_INTERNAL_ERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // ERR internal error on publish error
|
||||
return API_INTERNAL_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
static mqtt_app_err_t ResponceWithFile(int idx, espfs_file_t *file,
|
||||
char *id,
|
||||
char *url)
|
||||
{
|
||||
struct espfs_stat_t stat;
|
||||
char *filebuf = NULL;
|
||||
char *outbuf = NULL;
|
||||
uint32_t fileLenth, filePtr, readBytes;
|
||||
espfs_fstat(file, &stat);
|
||||
fileLenth = stat.size;
|
||||
mqtt_app_err_t api_err = API_UNKNOWN_ERR;
|
||||
if (fileLenth > MAX_FILE_PUBLISH)
|
||||
{
|
||||
ESP_LOGE(TAG, "File is too big");
|
||||
api_err = API_FILE_OVERSIZE_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
outbuf = (char*) malloc(MAX_FILE_PUBLISH + 256);
|
||||
filebuf = (char*) malloc(fileLenth);
|
||||
|
||||
if (!outbuf || !filebuf)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to allocate memory");
|
||||
api_err = API_INTERNAL_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
|
||||
if (espfs_fread(file, filebuf, fileLenth) == 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Read no bytes from file");
|
||||
api_err = API_FILE_EMPTY_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
espfs_fclose(file);
|
||||
|
||||
jwOpen(outbuf, MAX_FILE_PUBLISH, JW_OBJECT, JW_PRETTY);
|
||||
jwObj_string("messid", (char*) id);
|
||||
jwObj_string("api", (char*) apiver);
|
||||
jwObj_string("responce", (char*) mqtt_app_err_breef[API_OK]);
|
||||
jwObj_string("descript", (char*) mqtt_app_err_descr[API_OK]);
|
||||
jwObj_string("url", (char*) url);
|
||||
jwObj_string("body", "bodydata");
|
||||
jwEnd();
|
||||
jwClose();
|
||||
|
||||
char *fdata = memmem(outbuf, MAX_FILE_PUBLISH, "\"bodydata\"", strlen("\"bodydata\""));
|
||||
filePtr = 0;
|
||||
readBytes = 0;
|
||||
while (filePtr < fileLenth && readBytes < (MAX_FILE_PUBLISH - MAX_DYNVAR_LENTH))
|
||||
{
|
||||
if (filebuf[filePtr] == '~')
|
||||
{
|
||||
int k = 0;
|
||||
char DynVarName[16];
|
||||
while (filePtr < fileLenth && k < 16 && (filebuf[++filePtr] != '~'))
|
||||
DynVarName[k++] = filebuf[filePtr];
|
||||
if (filebuf[filePtr] == '~')
|
||||
{ //got valid dynamic variable name
|
||||
DynVarName[k] = 0x00;
|
||||
readBytes += HTTPPrint(NULL, &fdata[readBytes], DynVarName);
|
||||
filePtr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
fdata[readBytes++] = filebuf[filePtr++];
|
||||
}
|
||||
const char tail[] = "}";
|
||||
strcat((fdata + readBytes), tail);
|
||||
free(filebuf);
|
||||
DATA_SEND_STRUCT DSS;
|
||||
DSS.dt = PUBLISH_CONTROL_DATA;
|
||||
DSS.raw_data_ptr = outbuf;
|
||||
DSS.data_lenth = (fdata - outbuf) + readBytes + strlen(tail);
|
||||
if (xQueueSend(mqtt[idx].mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
||||
return API_OK;
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to write mqtt queue");
|
||||
api_err = API_INTERNAL_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
file_send_err:
|
||||
free(outbuf);
|
||||
free(filebuf);
|
||||
return api_err;
|
||||
}
|
||||
|
||||
static void ControlDataHandler(char *data, uint32_t len, int idx)
|
||||
{
|
||||
struct jReadElement result;
|
||||
char URL[MAX_FILENAME_LENTH + 1];
|
||||
char ID[MAX_MESSAGE_ID + 1];
|
||||
char POST_DATA[MAX_POST_DATA_LENTH + 1];
|
||||
mqtt_api_request_t req = UNSUPPORTED;
|
||||
mqtt_app_err_t api_err = API_UNKNOWN_ERR;
|
||||
ID[0] = 0x00;
|
||||
URL[0] = 0x00;
|
||||
espfs_file_t *file = NULL;
|
||||
|
||||
jRead(data, "", &result);
|
||||
if (result.dataType == JREAD_OBJECT)
|
||||
{
|
||||
/*Checking and get ID message*/
|
||||
jRead(data, "{'messid'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_MESSAGE_ID)
|
||||
{
|
||||
api_err = API_ID_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(ID, result.pValue, result.bytelen);
|
||||
ID[result.bytelen] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_ID_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get API version*/
|
||||
jRead(data, "{'api'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (memcmp(apiver, result.pValue, result.bytelen))
|
||||
{
|
||||
api_err = API_VERSION_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_API_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get request type POST, GET or UNSUPPORTED*/
|
||||
jRead(data, "{'request'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (!memcmp(tagGet, result.pValue, result.bytelen))
|
||||
req = GET;
|
||||
else if (!memcmp(tagPost, result.pValue, result.bytelen))
|
||||
req = POST;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_REQUEST_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get url*/
|
||||
jRead(data, "{'url'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_FILENAME_LENTH)
|
||||
{
|
||||
api_err = API_URL_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(URL, result.pValue, result.bytelen);
|
||||
URL[result.bytelen] = 0x00;
|
||||
file = espfs_fopen(fs, URL);
|
||||
if (!file)
|
||||
{
|
||||
api_err = API_URL_NOT_FOUND_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_URL_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
if (req == POST)
|
||||
{
|
||||
/*Checking and get POST DATA*/
|
||||
jRead(data, "{'postdata'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_POST_DATA_LENTH)
|
||||
{
|
||||
api_err = API_POSTDATA_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(POST_DATA, result.pValue, result.bytelen);
|
||||
POST_DATA[result.bytelen] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_POSTDATA_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
HTTPPostApp(NULL, URL, POST_DATA);
|
||||
|
||||
jRead(data, "{'reload'", &result);
|
||||
if (result.elements == 1 && !memcmp("true", result.pValue, result.bytelen))
|
||||
{
|
||||
if (ResponceWithFile(idx, file, ID, URL) == API_OK)
|
||||
return;
|
||||
else
|
||||
goto api_json_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ResponceWithError(idx, file, ID, URL, API_OK) != API_OK)
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for file MQTT message");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (req == GET)
|
||||
{
|
||||
//Here GET handler, send file wrapped into json
|
||||
if (ResponceWithFile(idx, file, ID, URL) == API_OK)
|
||||
return;
|
||||
else
|
||||
goto api_json_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_UNSUPPORTED_METHOD_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //ERR no json format
|
||||
api_err = API_WRONG_JSON_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
api_json_err:
|
||||
ESP_LOGE(TAG, "ERROR:%s:%s", mqtt_app_err_breef[api_err], mqtt_app_err_descr[api_err]);
|
||||
if (ResponceWithError(idx, file, ID, URL, api_err) != API_OK)
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for file MQTT message");
|
||||
}
|
||||
|
||||
void MQTTStart(void)
|
||||
{
|
||||
for (int i = 0; i < CONFIG_MQTT_CLIENTS_NUM; ++i)
|
||||
|
|
@ -749,9 +402,6 @@ void MQTTRun(void)
|
|||
|
||||
mqtt[0].mqtt_queue = MQTT1MessagesQueueHandle;
|
||||
mqtt[1].mqtt_queue = MQTT2MessagesQueueHandle;
|
||||
|
||||
|
||||
|
||||
start_mqtt();
|
||||
}
|
||||
|
||||
|
|
|
|||
376
src/MQTTSysHandler.c
Normal file
376
src/MQTTSysHandler.c
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/*! Copyright 2022 Bogdan Pilyugin
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* \file MQTTSysHandler.c
|
||||
* \version 1.0
|
||||
* \date 2022-08-19
|
||||
* \author Bogdan Pilyugin
|
||||
* \brief
|
||||
* \details
|
||||
* \copyright Apache License, Version 2.0
|
||||
*/
|
||||
|
||||
#include "MQTT.h"
|
||||
#include "jWrite.h"
|
||||
#include "jRead.h"
|
||||
#include "esp_log.h"
|
||||
#include "romfs.h"
|
||||
#include "HTTPServer.h"
|
||||
|
||||
#define MESSAGE_LENGTH 32 //base message length, mainly depended by radio requirements
|
||||
#define MAX_JSON_MESSAGE 256 //max size of mqtt message to publish
|
||||
#define MAX_FILE_PUBLISH 4096 //bufer for mqtt data publish
|
||||
#define MAX_DYNVAR_LENTH 64
|
||||
#define MAX_FILENAME_LENTH 15
|
||||
#define MAX_ERROR_MESSAGE 32
|
||||
#define MAX_ERROR_JSON 256
|
||||
#define MAX_MESSAGE_ID 15
|
||||
|
||||
#define MAX_POST_DATA_LENTH 512
|
||||
|
||||
#define TAG "MQTTSysHandler"
|
||||
|
||||
const char apiver[] = "2.0";
|
||||
const char tagGet[] = "GET";
|
||||
const char tagPost[] = "POST";
|
||||
|
||||
const char* mqtt_app_err_descr[] = {
|
||||
"Operation OK",
|
||||
"Internal error",
|
||||
"Wrong json format",
|
||||
"Key 'idmess' not found",
|
||||
"Key 'idmess' value too long",
|
||||
"Key 'api' not found",
|
||||
"API version not supported",
|
||||
"Key 'request' not found",
|
||||
"Unsupported HTTP method",
|
||||
"Key 'url' not found",
|
||||
"Key 'url' value too long",
|
||||
"URL not found",
|
||||
"Key 'postdata' not found",
|
||||
"Key 'postdata' too long",
|
||||
"File size too big",
|
||||
"File is empty",
|
||||
"Unknown error"
|
||||
};
|
||||
|
||||
const char* mqtt_app_err_breef[] = {
|
||||
"OK",
|
||||
"INTERNAL_ERR",
|
||||
"WRONG_JSON_ERR",
|
||||
"NO_ID_ERR",
|
||||
"ID_OVERSIZE_ERR",
|
||||
"NO_API_ERR",
|
||||
"VERSION_ERR",
|
||||
"NO_REQUEST_ERR",
|
||||
"UNSUPPORTED_METHOD_ERR",
|
||||
"NO_URL_ERR",
|
||||
"URL_OVERSIZE_ERR",
|
||||
"URL_NOT_FOUND_ERR",
|
||||
"NO_POSTDATA_ERR",
|
||||
"POSTDATA_OVERSIZE_ERR",
|
||||
"FILE_OVERSIZE_ERR",
|
||||
"FILE_EMPTY_ERR",
|
||||
"UNKNOWN_ERR"
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNSUPPORTED = 0,
|
||||
GET,
|
||||
POST
|
||||
} mqtt_api_request_t;
|
||||
|
||||
static mqtt_app_err_t ResponceWithError(int idx,
|
||||
espfs_file_t *file,
|
||||
char *id,
|
||||
char *url,
|
||||
mqtt_app_err_t api_err)
|
||||
{
|
||||
espfs_fclose(file);
|
||||
char JSONErrorMess[MAX_ERROR_JSON];
|
||||
jwOpen(JSONErrorMess, MAX_ERROR_JSON, JW_OBJECT, JW_PRETTY);
|
||||
if (id[0])
|
||||
jwObj_string("messid", (char*) id);
|
||||
else
|
||||
jwObj_string("messid", "ERROR");
|
||||
jwObj_string("api", (char*) apiver);
|
||||
jwObj_string("responce", (char*) mqtt_app_err_breef[api_err]);
|
||||
jwObj_string("descript", (char*) mqtt_app_err_descr[api_err]);
|
||||
if (url[0])
|
||||
jwObj_string("url", (char*) url);
|
||||
else
|
||||
jwObj_string("url", "ERROR");
|
||||
jwEnd();
|
||||
jwClose();
|
||||
char *buf = (char*) malloc(strlen(JSONErrorMess) + 1);
|
||||
if (buf)
|
||||
{
|
||||
memcpy(buf, JSONErrorMess, strlen(JSONErrorMess));
|
||||
DATA_SEND_STRUCT DSS;
|
||||
DSS.dt = PUBLISH_CONTROL_DATA;
|
||||
DSS.raw_data_ptr = buf;
|
||||
DSS.data_lenth = strlen(JSONErrorMess);
|
||||
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
||||
return API_OK;
|
||||
else
|
||||
{
|
||||
free(buf);
|
||||
return API_INTERNAL_ERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // ERR internal error on publish error
|
||||
return API_INTERNAL_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
static mqtt_app_err_t ResponceWithFile(int idx, espfs_file_t *file,
|
||||
char *id,
|
||||
char *url)
|
||||
{
|
||||
struct espfs_stat_t stat;
|
||||
char *filebuf = NULL;
|
||||
char *outbuf = NULL;
|
||||
uint32_t fileLenth, filePtr, readBytes;
|
||||
espfs_fstat(file, &stat);
|
||||
fileLenth = stat.size;
|
||||
mqtt_app_err_t api_err = API_UNKNOWN_ERR;
|
||||
if (fileLenth > MAX_FILE_PUBLISH)
|
||||
{
|
||||
ESP_LOGE(TAG, "File is too big");
|
||||
api_err = API_FILE_OVERSIZE_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
outbuf = (char*) malloc(MAX_FILE_PUBLISH + 256);
|
||||
filebuf = (char*) malloc(fileLenth);
|
||||
|
||||
if (!outbuf || !filebuf)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to allocate memory");
|
||||
api_err = API_INTERNAL_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
|
||||
if (espfs_fread(file, filebuf, fileLenth) == 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Read no bytes from file");
|
||||
api_err = API_FILE_EMPTY_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
espfs_fclose(file);
|
||||
|
||||
jwOpen(outbuf, MAX_FILE_PUBLISH, JW_OBJECT, JW_PRETTY);
|
||||
jwObj_string("messid", (char*) id);
|
||||
jwObj_string("api", (char*) apiver);
|
||||
jwObj_string("responce", (char*) mqtt_app_err_breef[API_OK]);
|
||||
jwObj_string("descript", (char*) mqtt_app_err_descr[API_OK]);
|
||||
jwObj_string("url", (char*) url);
|
||||
jwObj_string("body", "bodydata");
|
||||
jwEnd();
|
||||
jwClose();
|
||||
|
||||
char *fdata = memmem(outbuf, MAX_FILE_PUBLISH, "\"bodydata\"", strlen("\"bodydata\""));
|
||||
filePtr = 0;
|
||||
readBytes = 0;
|
||||
while (filePtr < fileLenth && readBytes < (MAX_FILE_PUBLISH - MAX_DYNVAR_LENTH))
|
||||
{
|
||||
if (filebuf[filePtr] == '~')
|
||||
{
|
||||
int k = 0;
|
||||
char DynVarName[16];
|
||||
while (filePtr < fileLenth && k < 16 && (filebuf[++filePtr] != '~'))
|
||||
DynVarName[k++] = filebuf[filePtr];
|
||||
if (filebuf[filePtr] == '~')
|
||||
{ //got valid dynamic variable name
|
||||
DynVarName[k] = 0x00;
|
||||
readBytes += HTTPPrint(NULL, &fdata[readBytes], DynVarName);
|
||||
filePtr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
fdata[readBytes++] = filebuf[filePtr++];
|
||||
}
|
||||
const char tail[] = "}";
|
||||
strcat((fdata + readBytes), tail);
|
||||
free(filebuf);
|
||||
DATA_SEND_STRUCT DSS;
|
||||
DSS.dt = PUBLISH_CONTROL_DATA;
|
||||
DSS.raw_data_ptr = outbuf;
|
||||
DSS.data_lenth = (fdata - outbuf) + readBytes + strlen(tail);
|
||||
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
||||
return API_OK;
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to write mqtt queue");
|
||||
api_err = API_INTERNAL_ERR;
|
||||
goto file_send_err;
|
||||
}
|
||||
file_send_err:
|
||||
free(outbuf);
|
||||
free(filebuf);
|
||||
return api_err;
|
||||
}
|
||||
|
||||
void ControlDataHandler(char *data, uint32_t len, int idx)
|
||||
{
|
||||
struct jReadElement result;
|
||||
char URL[MAX_FILENAME_LENTH + 1];
|
||||
char ID[MAX_MESSAGE_ID + 1];
|
||||
char POST_DATA[MAX_POST_DATA_LENTH + 1];
|
||||
mqtt_api_request_t req = UNSUPPORTED;
|
||||
mqtt_app_err_t api_err = API_UNKNOWN_ERR;
|
||||
ID[0] = 0x00;
|
||||
URL[0] = 0x00;
|
||||
espfs_file_t *file = NULL;
|
||||
|
||||
jRead(data, "", &result);
|
||||
if (result.dataType == JREAD_OBJECT)
|
||||
{
|
||||
/*Checking and get ID message*/
|
||||
jRead(data, "{'messid'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_MESSAGE_ID)
|
||||
{
|
||||
api_err = API_ID_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(ID, result.pValue, result.bytelen);
|
||||
ID[result.bytelen] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_ID_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get API version*/
|
||||
jRead(data, "{'api'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (memcmp(apiver, result.pValue, result.bytelen))
|
||||
{
|
||||
api_err = API_VERSION_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_API_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get request type POST, GET or UNSUPPORTED*/
|
||||
jRead(data, "{'request'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (!memcmp(tagGet, result.pValue, result.bytelen))
|
||||
req = GET;
|
||||
else if (!memcmp(tagPost, result.pValue, result.bytelen))
|
||||
req = POST;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_REQUEST_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
/*Checking and get url*/
|
||||
jRead(data, "{'url'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_FILENAME_LENTH)
|
||||
{
|
||||
api_err = API_URL_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(URL, result.pValue, result.bytelen);
|
||||
URL[result.bytelen] = 0x00;
|
||||
file = espfs_fopen(fs, URL);
|
||||
if (!file)
|
||||
{
|
||||
api_err = API_URL_NOT_FOUND_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_URL_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
if (req == POST)
|
||||
{
|
||||
/*Checking and get POST DATA*/
|
||||
jRead(data, "{'postdata'", &result);
|
||||
if (result.elements == 1)
|
||||
{
|
||||
if (result.bytelen > MAX_POST_DATA_LENTH)
|
||||
{
|
||||
api_err = API_POSTDATA_OVERSIZE_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
memcpy(POST_DATA, result.pValue, result.bytelen);
|
||||
POST_DATA[result.bytelen] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_NO_POSTDATA_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
HTTPPostApp(NULL, URL, POST_DATA);
|
||||
|
||||
jRead(data, "{'reload'", &result);
|
||||
if (result.elements == 1 && !memcmp("true", result.pValue, result.bytelen))
|
||||
{
|
||||
if (ResponceWithFile(idx, file, ID, URL) == API_OK)
|
||||
return;
|
||||
else
|
||||
goto api_json_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ResponceWithError(idx, file, ID, URL, API_OK) != API_OK)
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for file MQTT message");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (req == GET)
|
||||
{
|
||||
//Here GET handler, send file wrapped into json
|
||||
if (ResponceWithFile(idx, file, ID, URL) == API_OK)
|
||||
return;
|
||||
else
|
||||
goto api_json_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
api_err = API_UNSUPPORTED_METHOD_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //ERR no json format
|
||||
api_err = API_WRONG_JSON_ERR;
|
||||
goto api_json_err;
|
||||
}
|
||||
|
||||
api_json_err:
|
||||
ESP_LOGE(TAG, "ERROR:%s:%s", mqtt_app_err_breef[api_err], mqtt_app_err_descr[api_err]);
|
||||
if (ResponceWithError(idx, file, ID, URL, api_err) != API_OK)
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for file MQTT message");
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user