added application REST API test implementation
This commit is contained in:
parent
4120be5da9
commit
c30ed40c0b
|
|
@ -1 +1 @@
|
||||||
Subproject commit 32c90af2c182453caad7003c280e5223cadb5b87
|
Subproject commit d941791a466e7f8b7b73445d8f47a7a668decbd9
|
||||||
|
|
@ -23,6 +23,88 @@
|
||||||
#define MAIN_INCLUDE_APPLICATION_H_
|
#define MAIN_INCLUDE_APPLICATION_H_
|
||||||
|
|
||||||
#include "webguiapp.h"
|
#include "webguiapp.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "jRead.h"
|
||||||
|
#include "jWrite.h"
|
||||||
|
#include "AppConfiguration.h"
|
||||||
|
|
||||||
|
#define EXPECTED_MAX_DATA_RESPONSE_SIZE (2048)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
APP_OK_DATA = 0,
|
||||||
|
APP_OK,
|
||||||
|
|
||||||
|
APP_ERROR_WRONG_JSON_FORMAT = 200,
|
||||||
|
APP_ERROR_PARSE_DATA,
|
||||||
|
APP_ERROR_SHA256_DATA,
|
||||||
|
|
||||||
|
APP_ERROR_PARSE_SIGNATURE,
|
||||||
|
APP_ERROR_PARSE_MESSAGEID,
|
||||||
|
APP_ERROR_PARSE_MSGTYPE,
|
||||||
|
APP_ERROR_PARSE_PAYLOADTYPE,
|
||||||
|
|
||||||
|
APP_ERROR_PARSE_KEY1,
|
||||||
|
APP_ERROR_PARSE_KEY2,
|
||||||
|
|
||||||
|
APP_ERROR_NO_MEMORY = 300,
|
||||||
|
APP_ERROR_UNKNOWN,
|
||||||
|
|
||||||
|
} app_error_code;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
APP_MSG_COMMAND = 1,
|
||||||
|
APP_MSG_REQUEST,
|
||||||
|
APP_MSG_RESPONSE
|
||||||
|
} app_msg_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int key1;
|
||||||
|
int key2;
|
||||||
|
|
||||||
|
} payload_type_1;
|
||||||
|
|
||||||
|
|
||||||
|
#define DATA_MESSAGE_TYPE_COMMAND (1)
|
||||||
|
#define DATA_MESSAGE_TYPE_REQUEST (2)
|
||||||
|
#define DATA_MESSAGE_TYPE_RESPONSE (3)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *inputDataBuffer;
|
||||||
|
int inputDataLength;
|
||||||
|
int chlidx;
|
||||||
|
char *outputDataBuffer;
|
||||||
|
int outputDataLength;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t msgID;
|
||||||
|
time_t time;
|
||||||
|
int msgType;
|
||||||
|
int payloadType;
|
||||||
|
void *payload;
|
||||||
|
unsigned char sha256[32];
|
||||||
|
} parsedData;
|
||||||
|
int err_code;
|
||||||
|
} data_message_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char transID[64];
|
||||||
|
char transTime[32];
|
||||||
|
int64_t transact_sm_timer; // ocpp state machine timeout timer
|
||||||
|
int64_t interpulse_timer;
|
||||||
|
bool isActive;
|
||||||
|
|
||||||
|
bool isInitialised;
|
||||||
|
int idx;
|
||||||
|
} app_handle_t;
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t AppServiceDataHandler(data_message_t *MSG);
|
||||||
|
void GetAppErrorDetales(app_error_code err, const char **br, const char **ds);
|
||||||
|
|
||||||
HTTP_IO_RESULT HTTPPostCustomAPI(httpd_req_t *req, char *PostData);
|
HTTP_IO_RESULT HTTPPostCustomAPI(httpd_req_t *req, char *PostData);
|
||||||
|
|
||||||
|
|
|
||||||
288
main/src/AppComm.c
Normal file
288
main/src/AppComm.c
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
/*! Copyright 2023 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 SpiralControllerComm.c
|
||||||
|
* \version 1.0
|
||||||
|
* \date 2023-06-03
|
||||||
|
* \author Bogdan Pilyugin
|
||||||
|
* \brief
|
||||||
|
* \details
|
||||||
|
* \copyright Apache License, Version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
//Example of remote transaction [payloadtype=1] start[msgtype=1]
|
||||||
|
{
|
||||||
|
"data":{
|
||||||
|
"msgid":123456789,
|
||||||
|
"time":"2023-06-03T12:25:24+00:00",
|
||||||
|
"msgtype":1,
|
||||||
|
"payloadtype":1,
|
||||||
|
"payload":{
|
||||||
|
"key1":"value1",
|
||||||
|
"key2":"value2"}},
|
||||||
|
"signature":"6a11b872e8f766673eb82e127b6918a0dc96a42c5c9d184604f9787f3d27bcef"}
|
||||||
|
|
||||||
|
|
||||||
|
//Example of request [msgtype=2] of information related to transaction [payloadtype=1]
|
||||||
|
{
|
||||||
|
"data":{
|
||||||
|
"msgid":123456789,
|
||||||
|
"time":"2023-06-03T12:25:24+00:00",
|
||||||
|
"msgtype":2,
|
||||||
|
"payloadtype":1},
|
||||||
|
"signature":"3c1254d5b0e7ecc7e662dd6397554f02622ef50edba18d0b30ecb5d53e409bcb"}
|
||||||
|
|
||||||
|
|
||||||
|
//Example of response [msgtype=3] to request related to the transaction [payloadtype=1]
|
||||||
|
|
||||||
|
{
|
||||||
|
"data":{
|
||||||
|
"msgid":123456789,
|
||||||
|
"time":"2023-06-03T12:25:24+00:00",
|
||||||
|
"msgtype": 3,
|
||||||
|
"payloadtype":1,
|
||||||
|
"payload":{
|
||||||
|
"key1":"value1",
|
||||||
|
"key2":"value2"},
|
||||||
|
"error":"APP_OK",
|
||||||
|
"error_descr":"Result successful"},
|
||||||
|
"signature":"0d3b545b7c86274a6bf5a6e606b260f32b1999de40cb7d29d0949ecc9389cd9d"}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webguiapp.h"
|
||||||
|
#include "Application.h"
|
||||||
|
#include "mbedtls/md.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define TAG "AppComm"
|
||||||
|
|
||||||
|
#define MAX_JSON_DATA_SIZE 1024
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t SHA256hmacHash(unsigned char *data,
|
||||||
|
int datalen,
|
||||||
|
unsigned char *key,
|
||||||
|
int keylen,
|
||||||
|
unsigned char *res)
|
||||||
|
{
|
||||||
|
mbedtls_md_context_t ctx;
|
||||||
|
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||||
|
mbedtls_md_init(&ctx);
|
||||||
|
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1);
|
||||||
|
mbedtls_md_hmac_starts(&ctx, key, keylen);
|
||||||
|
mbedtls_md_hmac_update(&ctx, (const unsigned char*) data, datalen);
|
||||||
|
mbedtls_md_hmac_finish(&ctx, res);
|
||||||
|
mbedtls_md_free(&ctx);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Timestamp(char *ts)
|
||||||
|
{
|
||||||
|
struct timeval tp;
|
||||||
|
gettimeofday(&tp, NULL);
|
||||||
|
unsigned long long ms = (((unsigned long long) tp.tv_sec) * 1000000 + tp.tv_usec);
|
||||||
|
sprintf(ts, "%llu", ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
app_error_code StartTransactionPayloadType1(data_message_t *MSG)
|
||||||
|
{
|
||||||
|
payload_type_1 *payload;
|
||||||
|
payload = ((payload_type_1*) (MSG->parsedData.payload));
|
||||||
|
return APP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrepareResponsePayloadType1(data_message_t *MSG)
|
||||||
|
{
|
||||||
|
const char *err_br;
|
||||||
|
const char *err_desc;
|
||||||
|
jwOpen(MSG->outputDataBuffer, MSG->outputDataLength, JW_OBJECT, JW_PRETTY);
|
||||||
|
jwObj_int("msgid", MSG->parsedData.msgID);
|
||||||
|
char time[RFC3339_TIMESTAMP_LENGTH];
|
||||||
|
GetRFC3339Time(time);
|
||||||
|
jwObj_string("time", time);
|
||||||
|
jwObj_int("messtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||||
|
jwObj_int("payloadtype", 1);
|
||||||
|
//PAYLOAD BEGIN
|
||||||
|
jwObj_object("payload");
|
||||||
|
|
||||||
|
jwObj_string("param1", "value1");
|
||||||
|
jwObj_string("param2", "value2");
|
||||||
|
|
||||||
|
jwEnd();
|
||||||
|
GetAppErrorDetales((app_error_code) MSG->err_code, &err_br, &err_desc);
|
||||||
|
jwObj_string("error", (char*) err_br);
|
||||||
|
jwObj_string("error_descr", (char*) err_desc);
|
||||||
|
jwEnd();
|
||||||
|
jwClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static app_error_code AppPayloadType1Handler(data_message_t *MSG)
|
||||||
|
{
|
||||||
|
struct jReadElement result;
|
||||||
|
payload_type_1 *payload;
|
||||||
|
payload = ((payload_type_1*) (MSG->parsedData.payload));
|
||||||
|
if (MSG->parsedData.msgType == DATA_MESSAGE_TYPE_COMMAND)
|
||||||
|
{
|
||||||
|
//Extract 'key1' or throw exception
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'payload'{'key1'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_KEY1;
|
||||||
|
|
||||||
|
//Extract 'key1' or throw exception
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'payload'{'key2'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_KEY2;
|
||||||
|
|
||||||
|
return StartTransactionPayloadType1(MSG);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (MSG->parsedData.msgType == DATA_MESSAGE_TYPE_REQUEST)
|
||||||
|
{
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'payload'{'key1'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
return APP_OK_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_MSGTYPE;
|
||||||
|
|
||||||
|
return APP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static app_error_code AppDataParser(data_message_t *MSG)
|
||||||
|
{
|
||||||
|
struct jReadElement result;
|
||||||
|
jRead(MSG->inputDataBuffer, "", &result);
|
||||||
|
if (result.dataType != JREAD_OBJECT)
|
||||||
|
return APP_ERROR_WRONG_JSON_FORMAT;
|
||||||
|
MSG->parsedData.msgID = 0;
|
||||||
|
|
||||||
|
char *hashbuf = malloc(MSG->inputDataLength);
|
||||||
|
if (hashbuf == NULL)
|
||||||
|
return APP_ERROR_NO_MEMORY;
|
||||||
|
jRead_string(MSG->inputDataBuffer, "{'data'", hashbuf, MSG->inputDataLength, 0);
|
||||||
|
if (strlen(hashbuf) > 0)
|
||||||
|
{
|
||||||
|
SHA256hmacHash((unsigned char*) hashbuf, strlen(hashbuf), (unsigned char*) "mykey", sizeof("mykey"),
|
||||||
|
MSG->parsedData.sha256);
|
||||||
|
unsigned char sha_print[32 * 2 + 1];
|
||||||
|
BytesToStr(MSG->parsedData.sha256, sha_print, 32);
|
||||||
|
sha_print[32 * 2] = 0x00;
|
||||||
|
ESP_LOGI(TAG, "SHA256 of DATA object is %s", sha_print);
|
||||||
|
free(hashbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(hashbuf);
|
||||||
|
return APP_ERROR_PARSE_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(MSG->inputDataBuffer, "{'signature'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Signature is %.*s", 64, (char* )result.pValue);
|
||||||
|
//Here compare calculated and received signature;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_SIGNATURE;
|
||||||
|
|
||||||
|
//Extract 'messidx' or throw exception
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'msgid'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
MSG->parsedData.msgID = jRead_long(MSG->inputDataBuffer, "{'data'{'msgid'", 0);
|
||||||
|
if (MSG->parsedData.msgID == 0)
|
||||||
|
return APP_ERROR_PARSE_MESSAGEID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_MESSAGEID;
|
||||||
|
|
||||||
|
//Extract 'msgtype' or throw exception
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'msgtype'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
MSG->parsedData.msgType = atoi((char*) result.pValue);
|
||||||
|
if (MSG->parsedData.msgType > 2 || MSG->parsedData.msgType < 1)
|
||||||
|
return APP_ERROR_PARSE_MSGTYPE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_MSGTYPE;
|
||||||
|
|
||||||
|
//Extract 'payloadtype' or throw exception
|
||||||
|
jRead(MSG->inputDataBuffer, "{'data'{'payloadtype'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
MSG->parsedData.payloadType = atoi((char*) result.pValue);
|
||||||
|
if (MSG->parsedData.payloadType < 1 && MSG->parsedData.payloadType > 2)
|
||||||
|
return APP_ERROR_PARSE_PAYLOADTYPE;
|
||||||
|
MSG->parsedData.payload = malloc(sizeof(payload_type_1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return APP_ERROR_PARSE_PAYLOADTYPE;
|
||||||
|
|
||||||
|
switch (MSG->parsedData.payloadType)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
return AppPayloadType1Handler(MSG);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return APP_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t AppServiceDataHandler(data_message_t *MSG)
|
||||||
|
{
|
||||||
|
MSG->err_code = (int) AppDataParser(MSG);
|
||||||
|
if (MSG->err_code)
|
||||||
|
{
|
||||||
|
jwOpen(MSG->outputDataBuffer, MSG->outputDataLength, JW_OBJECT, JW_PRETTY);
|
||||||
|
jwObj_int("msgid", MSG->parsedData.msgID);
|
||||||
|
char time[RFC3339_TIMESTAMP_LENGTH];
|
||||||
|
GetRFC3339Time(time);
|
||||||
|
jwObj_string("time", time);
|
||||||
|
jwObj_int("messtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||||
|
const char *err_br;
|
||||||
|
const char *err_desc;
|
||||||
|
GetAppErrorDetales((app_error_code) MSG->err_code, &err_br, &err_desc);
|
||||||
|
jwObj_string("error", (char*) err_br);
|
||||||
|
jwObj_string("error_descr", (char*) err_desc);
|
||||||
|
jwEnd();
|
||||||
|
jwClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
70
main/src/AppErr.c
Normal file
70
main/src/AppErr.c
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*! Copyright 2023 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 SpiralControllerErr.c
|
||||||
|
* \version 1.0
|
||||||
|
* \date 2023-06-03
|
||||||
|
* \author Bogdan Pilyugin
|
||||||
|
* \brief
|
||||||
|
* \details
|
||||||
|
* \copyright Apache License, Version 2.0
|
||||||
|
*/
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
#define TAG "AppErr"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
app_error_code errcode;
|
||||||
|
char *errbreaf;
|
||||||
|
char *errdescr;
|
||||||
|
} spiral_error_t;
|
||||||
|
|
||||||
|
const spiral_error_t Errors[] = {
|
||||||
|
{APP_OK_DATA, "APP_OK_DATA", "Result successful, data attached" },
|
||||||
|
{APP_OK, "APP_OK", "Result successful" },
|
||||||
|
|
||||||
|
{ APP_ERROR_WRONG_JSON_FORMAT, "APP_ERROR_WRONG_JSON_FORMAT", "Wrong JSON format or not JSON data" },
|
||||||
|
{ APP_ERROR_PARSE_DATA, "APP_ERROR_PARSE_PAYLOAD", "Payload object not found"},
|
||||||
|
{ APP_ERROR_SHA256_DATA, "APP_ERROR_SHA256_PAYLOAD", "SHA256 signature is not valid"},
|
||||||
|
{ APP_ERROR_PARSE_SIGNATURE, "APP_ERROR_PARSE_SIGNATURE", "Key 'signature' not found"},
|
||||||
|
{ APP_ERROR_PARSE_MESSAGEID, "APP_ERROR_PARSE_MESSAGEID", "Key 'msgid' not found or have illegal value" },
|
||||||
|
{ APP_ERROR_PARSE_MSGTYPE, "APP_ERROR_PARSE_MSGTYPE", "Key 'msgtype' not found or have illegal value"},
|
||||||
|
{ APP_ERROR_PARSE_PAYLOADTYPE, "APP_ERROR_PARSE_PAYLOADTYPE", "Key 'payloadtype' not found or have illegal value"},
|
||||||
|
|
||||||
|
{ APP_ERROR_PARSE_KEY1, "APP_ERROR_PARSE_KEY1", "Key 'key1' not found or have illegal value"},
|
||||||
|
{ APP_ERROR_PARSE_KEY2, "APP_ERROR_PARSE_KEY2", "Key 'key2' not found or have illegal value"},
|
||||||
|
|
||||||
|
{ APP_ERROR_NO_MEMORY, "APP_ERROR_NO_MEMORY", "ERROR allocate memory for JSON parser" },
|
||||||
|
{ APP_ERROR_UNKNOWN, "APP_ERROR_UNKNOWN", "Unknown ERROR" }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetAppErrorDetales(app_error_code err, const char **br, const char **ds)
|
||||||
|
{
|
||||||
|
*br = Errors[sizeof(Errors) / sizeof(spiral_error_t) - 1].errbreaf;
|
||||||
|
*ds = Errors[sizeof(Errors) / sizeof(spiral_error_t) - 1].errdescr;
|
||||||
|
|
||||||
|
for (int i = 0; i < sizeof(Errors) / sizeof(spiral_error_t); i++)
|
||||||
|
{
|
||||||
|
if (err == Errors[i].errcode)
|
||||||
|
{
|
||||||
|
*br = Errors[i].errbreaf;
|
||||||
|
*ds = Errors[i].errdescr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -20,11 +20,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "webguiapp.h"
|
#include "webguiapp.h"
|
||||||
#include "jRead.h"
|
#include "Application.h"
|
||||||
#include "jWrite.h"
|
|
||||||
#include "AppConfiguration.h"
|
|
||||||
|
|
||||||
#define USER_API_VER "1.00"
|
#define USER_API_VER "1.00"
|
||||||
|
#define TAG "HTTPAPICustom"
|
||||||
|
|
||||||
HTTP_IO_RESULT HTTPPostCustomAPI(httpd_req_t *req, char *PostData)
|
HTTP_IO_RESULT HTTPPostCustomAPI(httpd_req_t *req, char *PostData)
|
||||||
{
|
{
|
||||||
|
|
@ -32,24 +31,26 @@ HTTP_IO_RESULT HTTPPostCustomAPI(httpd_req_t *req, char *PostData)
|
||||||
httpd_req_get_hdr_value_str(req, "Content-Type", (char*) data, 31);
|
httpd_req_get_hdr_value_str(req, "Content-Type", (char*) data, 31);
|
||||||
if (!memcmp(data, "application/json", sizeof("application/json")))
|
if (!memcmp(data, "application/json", sizeof("application/json")))
|
||||||
{
|
{
|
||||||
char key[32] = {0};
|
char *respbuf = malloc(EXPECTED_MAX_DATA_RESPONSE_SIZE);
|
||||||
struct jReadElement result;
|
if (respbuf)
|
||||||
jRead(PostData, "", &result);
|
|
||||||
if (result.dataType == JREAD_OBJECT)
|
|
||||||
{
|
{
|
||||||
jRead_string(PostData, "{'key'", key, sizeof(key), NULL);
|
data_message_t M = { 0 };
|
||||||
|
M.inputDataBuffer = PostData;
|
||||||
|
M.inputDataLength = strlen(PostData);
|
||||||
|
M.chlidx = 100;
|
||||||
|
M.outputDataBuffer = respbuf;
|
||||||
|
M.outputDataLength = EXPECTED_MAX_DATA_RESPONSE_SIZE;
|
||||||
|
AppServiceDataHandler(&M);
|
||||||
|
httpd_resp_sendstr(req, respbuf);
|
||||||
|
free(respbuf);
|
||||||
|
return HTTP_IO_DONE_API;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Out of free RAM for HTTP API handle");
|
||||||
|
httpd_resp_set_status(req, HTTPD_500);
|
||||||
|
return HTTP_IO_DONE_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ESP_LOGI(TAG, "JSON data:%s", PostData);
|
|
||||||
jwOpen(data, sizeof(data), JW_OBJECT, JW_COMPACT);
|
|
||||||
jwObj_string("apiver", USER_API_VER);
|
|
||||||
jwObj_string("apitype", "userapi");
|
|
||||||
jwObj_string("key", key);;
|
|
||||||
jwObj_raw("result", "OK");
|
|
||||||
jwEnd();
|
|
||||||
jwClose();
|
|
||||||
httpd_resp_sendstr(req, data);
|
|
||||||
return HTTP_IO_DONE_API;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_resp_set_status(req, HTTPD_400);
|
httpd_resp_set_status(req, HTTPD_400);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
* \copyright Apache License, Version 2.0
|
* \copyright Apache License, Version 2.0
|
||||||
*/
|
*/
|
||||||
#include "webguiapp.h"
|
#include "webguiapp.h"
|
||||||
#include "jRead.h"
|
|
||||||
#include "AppConfiguration.h"
|
#include "AppConfiguration.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "CronTimers.h"
|
#include "CronTimers.h"
|
||||||
|
|
@ -31,7 +30,7 @@ const char pg_42[] = "index42.html";
|
||||||
const char pg_43[] = "index43.html";
|
const char pg_43[] = "index43.html";
|
||||||
const char pg_44[] = "index44.html";
|
const char pg_44[] = "index44.html";
|
||||||
const char url_application[] = "application.html";
|
const char url_application[] = "application.html";
|
||||||
const char url_userapi[] = "userapi";
|
const char url_api[] = "api";
|
||||||
|
|
||||||
static HTTP_IO_RESULT HTTPPostIndex40(httpd_req_t *req, char *PostData);
|
static HTTP_IO_RESULT HTTPPostIndex40(httpd_req_t *req, char *PostData);
|
||||||
static HTTP_IO_RESULT HTTPPostIndex42(httpd_req_t *req, char *PostData);
|
static HTTP_IO_RESULT HTTPPostIndex42(httpd_req_t *req, char *PostData);
|
||||||
|
|
@ -41,7 +40,7 @@ static HTTP_IO_RESULT HTTPPostApplication(httpd_req_t *req, char *PostData);
|
||||||
|
|
||||||
HTTP_IO_RESULT AfterPostHandlerCustom(httpd_req_t *req, const char *filename, char *PostData)
|
HTTP_IO_RESULT AfterPostHandlerCustom(httpd_req_t *req, const char *filename, char *PostData)
|
||||||
{
|
{
|
||||||
if (!memcmp(filename, url_userapi, sizeof(url_userapi)))
|
if (!memcmp(filename, url_api, sizeof(url_api)))
|
||||||
return HTTPPostCustomAPI(req, PostData);
|
return HTTPPostCustomAPI(req, PostData);
|
||||||
if (!memcmp(filename, pg_40, sizeof(pg_40)))
|
if (!memcmp(filename, pg_40, sizeof(pg_40)))
|
||||||
return HTTPPostIndex40(req, PostData);
|
return HTTPPostIndex40(req, PostData);
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,22 @@
|
||||||
* \copyright Apache License, Version 2.0
|
* \copyright Apache License, Version 2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "webguiapp.h"
|
#include "Application.h"
|
||||||
|
|
||||||
#define TAG "MQTTCustom"
|
#define TAG "MQTTCustom"
|
||||||
|
|
||||||
esp_err_t UserMQTTSendExample(int idx)
|
esp_err_t AppServiceMQTTSend(char *data, int len, int idx)
|
||||||
{
|
{
|
||||||
const char resp[] = { "Got MQTT data in topic USER" };
|
if (GetMQTTHandlesPool(idx)->mqtt_queue == NULL)
|
||||||
char *buf = (char*) malloc(strlen(resp) + 1);
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
char *buf = (char*) malloc(len);
|
||||||
if (buf)
|
if (buf)
|
||||||
{
|
{
|
||||||
memcpy(buf, resp, strlen(resp));
|
memcpy(buf, data, len);
|
||||||
MQTT_DATA_SEND_STRUCT DSS;
|
MQTT_DATA_SEND_STRUCT DSS;
|
||||||
ComposeTopic(DSS.topic, idx, "USER", "UPLINK");
|
ComposeTopic(DSS.topic, idx, "APP", "UPLINK");
|
||||||
DSS.raw_data_ptr = buf;
|
DSS.raw_data_ptr = buf;
|
||||||
DSS.data_length = strlen(resp);
|
DSS.data_length = len;
|
||||||
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) == pdPASS)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
else
|
else
|
||||||
|
|
@ -42,11 +44,62 @@ esp_err_t UserMQTTSendExample(int idx)
|
||||||
free(buf);
|
free(buf);
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_MQTT_LOG_MESSAGE (1024)
|
||||||
|
|
||||||
|
#define APP_LOG_TAG "Application"
|
||||||
|
esp_err_t AppLog(esp_log_level_t level, char *format, ...)
|
||||||
|
{
|
||||||
|
char data[MAX_MQTT_LOG_MESSAGE];
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
va_end(arg);
|
||||||
|
vsnprintf(data, MAX_MQTT_LOG_MESSAGE, format, arg);
|
||||||
|
switch(level)
|
||||||
|
{
|
||||||
|
case ESP_LOG_INFO:
|
||||||
|
case ESP_LOG_DEBUG:
|
||||||
|
case ESP_LOG_VERBOSE:
|
||||||
|
case ESP_LOG_NONE:
|
||||||
|
ESP_LOGI(APP_LOG_TAG, "%s", data);
|
||||||
|
break;
|
||||||
|
case ESP_LOG_WARN:
|
||||||
|
ESP_LOGW(APP_LOG_TAG, "%s", data);
|
||||||
|
break;
|
||||||
|
case ESP_LOG_ERROR:
|
||||||
|
ESP_LOGE(APP_LOG_TAG, "%s", data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int idx = 0; idx < 2; idx++)
|
||||||
|
{
|
||||||
|
if (GetMQTTHandlesPool(idx)->mqtt_queue == NULL)
|
||||||
|
continue;
|
||||||
|
char time[RFC3339_TIMESTAMP_LENGTH];
|
||||||
|
GetRFC3339Time(time);
|
||||||
|
char *buf = (char*) malloc(strlen(data) + RFC3339_TIMESTAMP_LENGTH + 2);
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
strcpy(buf, time);
|
||||||
|
strcat(buf, " ");
|
||||||
|
strcat(buf, data);
|
||||||
|
MQTT_DATA_SEND_STRUCT DSS;
|
||||||
|
ComposeTopic(DSS.topic, idx, "LOG", "UPLINK");
|
||||||
|
DSS.raw_data_ptr = buf;
|
||||||
|
DSS.data_length = strlen(buf);
|
||||||
|
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) != pdPASS)
|
||||||
|
free(buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void UserMQTTEventHndlr(int idx, void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
void UserMQTTEventHndlr(int idx, void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||||
{
|
{
|
||||||
esp_mqtt_event_handle_t event = event_data;
|
esp_mqtt_event_handle_t event = event_data;
|
||||||
|
|
@ -58,19 +111,34 @@ void UserMQTTEventHndlr(int idx, void *handler_args, esp_event_base_t base, int3
|
||||||
switch ((esp_mqtt_event_id_t) event_id)
|
switch ((esp_mqtt_event_id_t) event_id)
|
||||||
{
|
{
|
||||||
case MQTT_EVENT_CONNECTED:
|
case MQTT_EVENT_CONNECTED:
|
||||||
ComposeTopic(topic, idx, "USER", "DWLINK");
|
ComposeTopic(topic, idx, "APP", "DWLINK");
|
||||||
//Subscribe to the service called "USER"
|
//Subscribe to the service called "APP"
|
||||||
msg_id = esp_mqtt_client_subscribe(client, (const char*) topic, 0);
|
msg_id = esp_mqtt_client_subscribe(client, (const char*) topic, 0);
|
||||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MQTT_EVENT_DATA:
|
case MQTT_EVENT_DATA:
|
||||||
ComposeTopic(topic, idx, "USER", "DWLINK");
|
ComposeTopic(topic, idx, "APP", "DWLINK");
|
||||||
if (!memcmp(topic, event->topic, event->topic_len))
|
if (!memcmp(topic, event->topic, event->topic_len))
|
||||||
{
|
{
|
||||||
//Here data for service called "USER"
|
char *respbuf = malloc(EXPECTED_MAX_DATA_RESPONSE_SIZE);
|
||||||
UserMQTTSendExample(idx);
|
if (respbuf != NULL)
|
||||||
ESP_LOGI(TAG, "USER data handler on client %d", idx);
|
{
|
||||||
|
data_message_t M = { 0 };
|
||||||
|
M.inputDataBuffer = event->data;
|
||||||
|
M.inputDataLength = event->data_len;
|
||||||
|
M.chlidx = idx;
|
||||||
|
M.outputDataBuffer = respbuf;
|
||||||
|
M.outputDataLength = EXPECTED_MAX_DATA_RESPONSE_SIZE;
|
||||||
|
AppServiceDataHandler(&M);
|
||||||
|
AppServiceMQTTSend(M.outputDataBuffer, strlen(M.outputDataBuffer), idx);
|
||||||
|
free(respbuf);
|
||||||
|
#if(MQTT_CUSTOM_HANDLER_DEBUG > 0)
|
||||||
|
ESP_LOGI(TAG, "SERVICE data handler on client %d", idx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ESP_LOGE(TAG, "Out of free RAM for MQTT API handle");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -79,3 +147,28 @@ void UserMQTTEventHndlr(int idx, void *handler_args, esp_event_base_t base, int3
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PublishTestApp(int idx)
|
||||||
|
{
|
||||||
|
char tmp[10];
|
||||||
|
char resp[256];
|
||||||
|
char data[512];
|
||||||
|
jwOpen(data, sizeof(data), JW_OBJECT, JW_PRETTY);
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
jwObj_int("time", (unsigned int) now);
|
||||||
|
jwObj_string("event", "APP_TEST_MESSAGE");
|
||||||
|
strcpy(resp, "mqtt://");
|
||||||
|
strcat(resp, GetSysConf()->mqttStation[idx].ServerAddr);
|
||||||
|
itoa(GetSysConf()->mqttStation[idx].ServerPort, tmp, 10);
|
||||||
|
strcat(resp, ":");
|
||||||
|
strcat(resp, tmp);
|
||||||
|
jwObj_string("url", resp);
|
||||||
|
ComposeTopic(resp, idx, "APP", "UPLINK");
|
||||||
|
jwObj_string("tx_topic", resp);
|
||||||
|
ComposeTopic(resp, idx, "APP", "DWLINK");
|
||||||
|
jwObj_string("rx_topic", resp);
|
||||||
|
jwEnd();
|
||||||
|
jwClose();
|
||||||
|
AppServiceMQTTSend(data, strlen(data), idx);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user