Compare commits
56 Commits
8f5537fd6a
...
147c2b9cdd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
147c2b9cdd | ||
|
|
8a1027a408 | ||
| b7ec9c8c35 | |||
|
|
a95e66c4b5 | ||
| 9b10a7f23d | |||
| bc0660ef35 | |||
| 26e104afe5 | |||
|
|
0edc230a47 | ||
|
|
d58ce6af9c | ||
|
|
a1f7694bdb | ||
|
|
3fe41b0f2e | ||
|
|
44d7c8d539 | ||
| b706e5ab26 | |||
|
|
b8f649b371 | ||
| 7058e86538 | |||
|
|
775635019c | ||
|
|
f48880e78a | ||
| 9276d4a6c1 | |||
|
|
6cb5bc0e9c | ||
| 0edd07fbd2 | |||
|
|
0a21101817 | ||
|
|
8b8ea9a57f | ||
|
|
a7417df420 | ||
| 394a798a98 | |||
| 9f20a1b08b | |||
| 92a1cc3cc7 | |||
| 513c9f6b89 | |||
| 3609a28892 | |||
| 7346de2bdf | |||
| 96a7238065 | |||
| 298c2e6534 | |||
| a64de4a0c5 | |||
| 9d54a977fc | |||
| a9b4f515d5 | |||
| f0a773b53f | |||
| cda4bc7722 | |||
| cef4def7f5 | |||
| c9beeaa39c | |||
| 8e2490bef0 | |||
| 4eaaff65fd | |||
| 94ff29e312 | |||
| 428bb65c7b | |||
| 27cbfffb5b | |||
| 78dbc8e917 | |||
| 3a7bf2a635 | |||
| 3858722cca | |||
| 4fdec54608 | |||
| db5452fe8b | |||
| 2d8e4ee592 | |||
| b473c8f198 | |||
| 25feb4f9fb | |||
| 83ab4dcba2 | |||
| ec5069c096 | |||
| 84257e8276 | |||
| 9b11542f1a | |||
| 5aaa2004c3 |
|
|
@ -16,8 +16,6 @@ idf_component_register(
|
||||||
"src/HTTPServer.c"
|
"src/HTTPServer.c"
|
||||||
"src/FileServer.c"
|
"src/FileServer.c"
|
||||||
"src/HTTPAPISystem.c"
|
"src/HTTPAPISystem.c"
|
||||||
# "src/HTTPPrintSystem.c"
|
|
||||||
# "src/HTTPPostSystem.c"
|
|
||||||
"src/CommandProcSys.c"
|
"src/CommandProcSys.c"
|
||||||
"src/Helpers.c"
|
"src/Helpers.c"
|
||||||
"src/NetTransport.c"
|
"src/NetTransport.c"
|
||||||
|
|
@ -27,11 +25,13 @@ idf_component_register(
|
||||||
"src/MQTT.c"
|
"src/MQTT.c"
|
||||||
"src/CronTimers.c"
|
"src/CronTimers.c"
|
||||||
"src/SerialPort.c"
|
"src/SerialPort.c"
|
||||||
src/RawMemAPI.c
|
src/sdcard.c
|
||||||
|
src/FileBlockHandler.c
|
||||||
src/OTA.c
|
src/OTA.c
|
||||||
src/RestApiHandler.c
|
src/RestApiHandler.c
|
||||||
src/SysComm.c
|
src/SysComm.c
|
||||||
src/SysErr.c
|
src/SysErr.c
|
||||||
|
src/EEPROM.c
|
||||||
${lora_SRCS}
|
${lora_SRCS}
|
||||||
${gprs_SRCS}
|
${gprs_SRCS}
|
||||||
${jreadwrite_SRCS}
|
${jreadwrite_SRCS}
|
||||||
|
|
@ -47,6 +47,7 @@ idf_component_register(
|
||||||
|
|
||||||
REQUIRES nvs_flash
|
REQUIRES nvs_flash
|
||||||
spiffs
|
spiffs
|
||||||
|
fatfs
|
||||||
esp_http_server
|
esp_http_server
|
||||||
mbedtls
|
mbedtls
|
||||||
lwip
|
lwip
|
||||||
|
|
|
||||||
67
Kconfig
67
Kconfig
|
|
@ -180,7 +180,7 @@ menu "WebGUIApp"
|
||||||
endif
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
menu "SPI settings"
|
menu "SPI settings"
|
||||||
config WEBGUIAPP_SPI_ENABLE
|
config WEBGUIAPP_SPI_ENABLE
|
||||||
bool "Enabled SPI interface"
|
bool "Enabled SPI interface"
|
||||||
|
|
@ -260,6 +260,57 @@ menu "WebGUIApp"
|
||||||
endif
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
|
menu "SDCARD settings"
|
||||||
|
config SDCARD_ENABLE
|
||||||
|
bool "Enabled SDCARD interface"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Set enabled SDCARD
|
||||||
|
|
||||||
|
if SDCARD_ENABLE
|
||||||
|
|
||||||
|
config SDCARD_SPI_HOST
|
||||||
|
int "SPI Host Number"
|
||||||
|
range 0 2
|
||||||
|
default 2
|
||||||
|
help
|
||||||
|
Set the SPI host used.
|
||||||
|
|
||||||
|
config SDCARD_SPI_CS_GPIO
|
||||||
|
int "SDCARD SPI CS GPIO number"
|
||||||
|
range GPIO_RANGE_MIN GPIO_RANGE_MAX
|
||||||
|
default 0 if IDF_TARGET_ESP32
|
||||||
|
default 0 if IDF_TARGET_ESP32S3
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SPI SCLK.
|
||||||
|
|
||||||
|
config SDCARD_SPI_SCLK_GPIO
|
||||||
|
int "SDCARD SPI SCLK GPIO number"
|
||||||
|
range GPIO_RANGE_MIN GPIO_RANGE_MAX
|
||||||
|
default 9 if IDF_TARGET_ESP32
|
||||||
|
default 9 if IDF_TARGET_ESP32S3
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SPI SCLK.
|
||||||
|
|
||||||
|
config SDCARD_SPI_MOSI_GPIO
|
||||||
|
int "SDCARD SPI MOSI GPIO number"
|
||||||
|
range GPIO_RANGE_MIN GPIO_RANGE_MAX
|
||||||
|
default 34 if IDF_TARGET_ESP32
|
||||||
|
default 44 if IDF_TARGET_ESP32S3
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SPI MOSI.
|
||||||
|
|
||||||
|
config SDCARD_SPI_MISO_GPIO
|
||||||
|
int "SDCARD SPI MISO GPIO number"
|
||||||
|
range GPIO_RANGE_MIN GPIO_RANGE_MAX
|
||||||
|
default 33 if IDF_TARGET_ESP32
|
||||||
|
default 43 if IDF_TARGET_ESP32S3
|
||||||
|
help
|
||||||
|
Set the GPIO number used by SPI MISO.
|
||||||
|
|
||||||
|
endif
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
menu "WiFi settings"
|
menu "WiFi settings"
|
||||||
|
|
@ -865,8 +916,6 @@ menu "WebGUIApp"
|
||||||
endif
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
menu "MQTT settings"
|
menu "MQTT settings"
|
||||||
config WEBGUIAPP_MQTT_ENABLE
|
config WEBGUIAPP_MQTT_ENABLE
|
||||||
bool "Enabled MQTT transport"
|
bool "Enabled MQTT transport"
|
||||||
|
|
@ -930,6 +979,18 @@ menu "WebGUIApp"
|
||||||
endif
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "System log"
|
||||||
|
config WEBGUIAPP_SYSLOG_MAX_CHUNKS
|
||||||
|
int "Number of syslog parts"
|
||||||
|
range 1 10
|
||||||
|
default 4
|
||||||
|
|
||||||
|
config WEBGUIAPP_SYSLOG_CHUNK_SIZE
|
||||||
|
int "Size of one part in kilobytes"
|
||||||
|
range 1 256
|
||||||
|
default 50
|
||||||
|
endmenu
|
||||||
|
|
||||||
if WEBGUIAPP_WIFI_ENABLE || WEBGUIAPP_ETHERNET_ENABLE || WEBGUIAPP_GPRS_ENABLE
|
if WEBGUIAPP_WIFI_ENABLE || WEBGUIAPP_ETHERNET_ENABLE || WEBGUIAPP_GPRS_ENABLE
|
||||||
menu "DNS settings"
|
menu "DNS settings"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,13 +50,14 @@ typedef struct
|
||||||
bool del; /*!< Flag of non valid record, free for future overwrite */
|
bool del; /*!< Flag of non valid record, free for future overwrite */
|
||||||
bool enab; /*!< Enable scheduler */
|
bool enab; /*!< Enable scheduler */
|
||||||
bool prev; /*!< Enable to execute nearest in the past sheduled action */
|
bool prev; /*!< Enable to execute nearest in the past sheduled action */
|
||||||
|
int type; /*!< Type: manual, sunrise, sunset, more types... */
|
||||||
|
float sun_angle;/*!<Sun angle unconditional event issue*/
|
||||||
char name[TIMER_NAME_LENGTH]; /*!< Human readable name of scheduler */
|
char name[TIMER_NAME_LENGTH]; /*!< Human readable name of scheduler */
|
||||||
char cron[TIMER_CRONSTRING_LENGTH]; /*!< Cron expression */
|
char cron[TIMER_CRONSTRING_LENGTH]; /*!< Cron expression */
|
||||||
char exec[TIMER_EXECSTRING_LENGTH]; /*!< Cron command string */
|
char exec[TIMER_EXECSTRING_LENGTH]; /*!< Cron command string */
|
||||||
|
|
||||||
} cron_timer_t;
|
} cron_timer_t;
|
||||||
|
|
||||||
esp_err_t InitCronSheduler();
|
|
||||||
esp_err_t ReloadCronSheduler();
|
esp_err_t ReloadCronSheduler();
|
||||||
char* GetCronError();
|
char* GetCronError();
|
||||||
void DebugTimer();
|
void DebugTimer();
|
||||||
|
|
@ -67,12 +68,15 @@ char* GetCronActionName(int idx);
|
||||||
char* GetCronActAvail(int idx);
|
char* GetCronActAvail(int idx);
|
||||||
|
|
||||||
void TimeObtainHandler(struct timeval *tm);
|
void TimeObtainHandler(struct timeval *tm);
|
||||||
|
void CronRecordsInterface(char *argres, int rw);
|
||||||
|
void AstroRecordsInterface(char *argres, int rw);
|
||||||
/**
|
/**
|
||||||
* \brief Handle all actions under all objects
|
* \brief Handle all actions under all objects
|
||||||
* \param obj Index of the object
|
* \param obj Index of the object
|
||||||
* \param act Index of the action
|
* \param act Index of the action
|
||||||
*/
|
*/
|
||||||
void custom_cron_execute(int obj, int act);
|
void custom_cron_execute(int obj, int act);
|
||||||
|
void SetSunTimes(uint32_t t);
|
||||||
|
void MidnightTimer();
|
||||||
|
|
||||||
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_CRONTIMERS_H_ */
|
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_CRONTIMERS_H_ */
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
|
|
||||||
/* Max length a file path can have on storage */
|
/* Max length a file path can have on storage */
|
||||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
|
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
|
||||||
#define MAX_FILE_SIZE (1000*1024) // 200 KB
|
#define MAX_FILE_SIZE (100*1000*1024) // 200 KB
|
||||||
#define MAX_FILE_SIZE_STR "1MB"
|
#define MAX_FILE_SIZE_STR "100MB"
|
||||||
|
|
||||||
/* Scratch buffer size */
|
/* Scratch buffer size */
|
||||||
#define SCRATCH_BUFSIZE EXPECTED_MAX_DATA_SIZE
|
#define SCRATCH_BUFSIZE EXPECTED_MAX_DATA_SIZE
|
||||||
|
|
@ -84,6 +84,23 @@ typedef struct
|
||||||
void (*HandlerRoutine)(char *VarData, void *arg);
|
void (*HandlerRoutine)(char *VarData, void *arg);
|
||||||
} dyn_var_handler_t;
|
} dyn_var_handler_t;
|
||||||
|
|
||||||
|
#define BLOCK_OPERATION_TIMEOUT 30
|
||||||
|
#define MEM_OBLECT_MAX_LENGTH 32
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int transid;
|
||||||
|
int opertype;
|
||||||
|
int operphase;
|
||||||
|
int part;
|
||||||
|
int parts;
|
||||||
|
int size;
|
||||||
|
char mem_object[MEM_OBLECT_MAX_LENGTH];
|
||||||
|
char filepath[FILE_PATH_MAX];
|
||||||
|
struct stat file_stat;
|
||||||
|
FILE *f;
|
||||||
|
int open_file_timeout;
|
||||||
|
} cb_blockdata_transfer_t;
|
||||||
|
|
||||||
esp_err_t start_file_server(void);
|
esp_err_t start_file_server(void);
|
||||||
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData);
|
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData);
|
||||||
int HTTPPrint(httpd_req_t *req, char* buf, char* var);
|
int HTTPPrint(httpd_req_t *req, char* buf, char* var);
|
||||||
|
|
@ -93,5 +110,9 @@ esp_err_t download_get_handler(httpd_req_t *req);
|
||||||
esp_err_t upload_post_handler(httpd_req_t *req);
|
esp_err_t upload_post_handler(httpd_req_t *req);
|
||||||
esp_err_t delete_post_handler(httpd_req_t *req);
|
esp_err_t delete_post_handler(httpd_req_t *req);
|
||||||
|
|
||||||
|
esp_err_t ParseBlockDataObject(char *argres, cb_blockdata_transfer_t *ft);
|
||||||
|
void FileBlockHandler(char *argres, int rw, const char* path);
|
||||||
|
void FileListHandler(char *argres, int rw, const char* path);
|
||||||
|
void FileBlockTimeoutCounter();
|
||||||
|
|
||||||
#endif /* COMPONENTS_WEB_GUI_APPLICATION_INCLUDE_HTTPSERVER_H_ */
|
#endif /* COMPONENTS_WEB_GUI_APPLICATION_INCLUDE_HTTPSERVER_H_ */
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@ typedef int mqtt_app_err_t;
|
||||||
#define API_FILE_EMPTY_ERR 15
|
#define API_FILE_EMPTY_ERR 15
|
||||||
#define API_UNKNOWN_ERR 16
|
#define API_UNKNOWN_ERR 16
|
||||||
|
|
||||||
|
#define EXTERNAL_SERVICE_NAME "RS485"
|
||||||
|
#define UPLINK_SUBTOPIC "UPLINK" // Device publish to this topic
|
||||||
|
#define DOWNLINK_SUBTOPIC "DWLINK" // Device listen from this topic
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char topic[CONFIG_WEBGUIAPP_MQTT_MAX_TOPIC_LENGTH];
|
char topic[CONFIG_WEBGUIAPP_MQTT_MAX_TOPIC_LENGTH];
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,8 @@ void GotEthIF(void);
|
||||||
void GetRFC3339Time(char *t);
|
void GetRFC3339Time(char *t);
|
||||||
void GetISO8601Time(char *t);
|
void GetISO8601Time(char *t);
|
||||||
void StartTimeGet(void);
|
void StartTimeGet(void);
|
||||||
|
void SetSystemTime(struct tm *time, const char* source);
|
||||||
|
void SetSystemTimeVal(struct timeval *tv, const char* source);
|
||||||
|
|
||||||
esp_err_t StartOTA(bool isManual);
|
esp_err_t StartOTA(bool isManual);
|
||||||
char* GetAvailVersion();
|
char* GetAvailVersion();
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/* Copyright 2024 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 name: RawMemAPI.h
|
|
||||||
* Project: WebguiappTemplate
|
|
||||||
* Created on: 2024-03-11
|
|
||||||
* Author: bogd
|
|
||||||
* Description:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COMPONENTS_WEBGUIAPP_INCLUDE_RAWMEMAPI_H_
|
|
||||||
#define COMPONENTS_WEBGUIAPP_INCLUDE_RAWMEMAPI_H_
|
|
||||||
#include "webguiapp.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool isActive;
|
|
||||||
int operType;
|
|
||||||
int dataLengthTotal;
|
|
||||||
int dataLengthReady;
|
|
||||||
} mqtt_files_cb;
|
|
||||||
|
|
||||||
void RawDataHandler(char *argres, int rw);
|
|
||||||
|
|
||||||
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_RAWMEMAPI_H_ */
|
|
||||||
|
|
@ -43,7 +43,8 @@ typedef enum{
|
||||||
VAR_STRING,
|
VAR_STRING,
|
||||||
VAR_PASS,
|
VAR_PASS,
|
||||||
VAR_IPADDR,
|
VAR_IPADDR,
|
||||||
VAR_FUNCT
|
VAR_FUNCT,
|
||||||
|
VAR_CHAR
|
||||||
} rest_var_types;
|
} rest_var_types;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,6 +104,9 @@ typedef struct
|
||||||
{
|
{
|
||||||
bool bIsGlobalEnabled;
|
bool bIsGlobalEnabled;
|
||||||
} Flags1;
|
} Flags1;
|
||||||
|
float lat;
|
||||||
|
float lon;
|
||||||
|
|
||||||
} sntpClient;
|
} sntpClient;
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ typedef struct
|
||||||
}UART_DATA_SEND_STRUCT;
|
}UART_DATA_SEND_STRUCT;
|
||||||
|
|
||||||
void InitSerialPort(void);
|
void InitSerialPort(void);
|
||||||
|
void InitSysSDCard();
|
||||||
esp_err_t TransmitSerialPort(char *data, int ln);
|
esp_err_t TransmitSerialPort(char *data, int ln);
|
||||||
|
|
||||||
esp_err_t GetConfVar(char* name, char* val, rest_var_types *tp);
|
esp_err_t GetConfVar(char* name, char* val, rest_var_types *tp);
|
||||||
|
|
@ -120,4 +121,9 @@ esp_err_t ServiceDataHandler(data_message_t *MSG);
|
||||||
sys_error_code SysVarsPayloadHandler(data_message_t *MSG);
|
sys_error_code SysVarsPayloadHandler(data_message_t *MSG);
|
||||||
void GetSysErrorDetales(sys_error_code err, const char **br, const char **ds);
|
void GetSysErrorDetales(sys_error_code err, const char **br, const char **ds);
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEBGUIAPP_I2C_ENABLE
|
||||||
|
esp_err_t eepr_i2c_read(uint16_t addr, uint8_t *data, int length);
|
||||||
|
esp_err_t eepr_i2c_write(uint16_t addr, uint8_t *data, int length);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_SYSTEMAPPLICATION_H_ */
|
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_SYSTEMAPPLICATION_H_ */
|
||||||
|
|
|
||||||
|
|
@ -42,5 +42,6 @@ void SetAppVars( rest_var_t* appvars, int size);
|
||||||
bool GetUserAppNeedReset(void);
|
bool GetUserAppNeedReset(void);
|
||||||
void SetUserAppNeedReset(bool res);
|
void SetUserAppNeedReset(bool res);
|
||||||
void LogFile(char *fname, char *format, ...);
|
void LogFile(char *fname, char *format, ...);
|
||||||
|
void SysLog(char *format, ...);
|
||||||
|
|
||||||
#endif /* COMPONENTS_WEBGUIAPPCOMPONENT_INCLUDE_WEBGUIAPP_H_ */
|
#endif /* COMPONENTS_WEBGUIAPPCOMPONENT_INCLUDE_WEBGUIAPP_H_ */
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ static int ExecCommandParse(char *cmd)
|
||||||
//int err = 0;
|
//int err = 0;
|
||||||
int commlen = strlen(cmd);
|
int commlen = strlen(cmd);
|
||||||
if (commlen > CONFIG_WEBGUIAPP_MAX_COMMAND_STRING_LENGTH)
|
if (commlen > CONFIG_WEBGUIAPP_MAX_COMMAND_STRING_LENGTH)
|
||||||
return 1;
|
return 1; //ERROR_TOO_LONG_COMMAND
|
||||||
char comm[CONFIG_WEBGUIAPP_MAX_COMMAND_STRING_LENGTH + 1];
|
char comm[CONFIG_WEBGUIAPP_MAX_COMMAND_STRING_LENGTH + 1];
|
||||||
|
|
||||||
strcpy(comm, cmd);
|
strcpy(comm, cmd);
|
||||||
|
|
@ -155,9 +155,9 @@ static int ExecCommandParse(char *cmd)
|
||||||
com = strtok(NULL, ",");
|
com = strtok(NULL, ",");
|
||||||
arg = strtok(NULL, "\0");
|
arg = strtok(NULL, "\0");
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return 2;
|
return 2; //ERROR_OBJECT_NOT_PARSED
|
||||||
if (!com)
|
if (!com)
|
||||||
return 3;
|
return 3; //ERROR_ACTION_NOT_PARSED
|
||||||
|
|
||||||
for (int idx = 0; idx < CONFIG_WEBGUIAPP_MAX_OBJECTS_NUM; idx++)
|
for (int idx = 0; idx < CONFIG_WEBGUIAPP_MAX_OBJECTS_NUM; idx++)
|
||||||
{
|
{
|
||||||
|
|
@ -170,13 +170,13 @@ static int ExecCommandParse(char *cmd)
|
||||||
if (com_obj_arr[idx].command_handlers[i] != NULL)
|
if (com_obj_arr[idx].command_handlers[i] != NULL)
|
||||||
{
|
{
|
||||||
com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
||||||
return 0;
|
return 0; //EXECUTED_OK
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 6;
|
return 6; //ERROR_HANDLER_NOT_IMPLEMENTED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 5;
|
return 5; //ERROR_ACTION_NOT_FOUND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,15 +191,15 @@ static int ExecCommandParse(char *cmd)
|
||||||
if (custom_com_obj_arr[idx].command_handlers[i] != NULL)
|
if (custom_com_obj_arr[idx].command_handlers[i] != NULL)
|
||||||
{
|
{
|
||||||
custom_com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
custom_com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
||||||
return 0;
|
return 0; //EXECUTED_OK
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 6;
|
return 6; //ERROR_HANDLER_NOT_IMPLEMENTED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 5;
|
return 5; //ERROR_ACTION_NOT_FOUND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 4;
|
return 4; //ERROR_OBJECT_NOT_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
249
src/CronTimers.c
249
src/CronTimers.c
|
|
@ -23,12 +23,18 @@
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "webguiapp.h"
|
#include "webguiapp.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
|
||||||
#define TAG "CRON_TIMER"
|
#define TAG "CRON_TIMER"
|
||||||
|
|
||||||
static cron_job *JobsList[CONFIG_WEBGUIAPP_CRON_NUMBER];
|
static cron_job *JobsList[CONFIG_WEBGUIAPP_CRON_NUMBER];
|
||||||
static char cron_express_error[CRON_EXPRESS_MAX_LENGTH];
|
static char cron_express_error[CRON_EXPRESS_MAX_LENGTH];
|
||||||
|
|
||||||
|
static int GetSunEvent(uint8_t event, uint32_t unixt, float ang);
|
||||||
|
static int RecalcAstro(uint32_t tt);
|
||||||
|
|
||||||
char* GetCronError()
|
char* GetCronError()
|
||||||
{
|
{
|
||||||
return cron_express_error;
|
return cron_express_error;
|
||||||
|
|
@ -39,12 +45,6 @@ void custom_cron_job_callback(cron_job *job)
|
||||||
ExecCommand(((cron_timer_t*) job->data)->exec);
|
ExecCommand(((cron_timer_t*) job->data)->exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t InitCronSheduler()
|
|
||||||
{
|
|
||||||
esp_err_t res = ESP_OK;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* check_expr(const char *expr)
|
const char* check_expr(const char *expr)
|
||||||
{
|
{
|
||||||
const char *err = NULL;
|
const char *err = NULL;
|
||||||
|
|
@ -105,6 +105,7 @@ static void ExecuteLastAction(obj_struct_t *objarr)
|
||||||
void TimeObtainHandler(struct timeval *tm)
|
void TimeObtainHandler(struct timeval *tm)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Current time updated with value %d", (unsigned int )tm->tv_sec);
|
ESP_LOGI(TAG, "Current time updated with value %d", (unsigned int )tm->tv_sec);
|
||||||
|
RecalcAstro(tm->tv_sec);
|
||||||
ReloadCronSheduler();
|
ReloadCronSheduler();
|
||||||
ExecuteLastAction(GetSystemObjects());
|
ExecuteLastAction(GetSystemObjects());
|
||||||
ExecuteLastAction(GetCustomObjects());
|
ExecuteLastAction(GetCustomObjects());
|
||||||
|
|
@ -150,3 +151,239 @@ esp_err_t ReloadCronSheduler()
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CronRecordsInterface(char *argres, int rw)
|
||||||
|
{
|
||||||
|
if (rw)
|
||||||
|
{
|
||||||
|
struct jReadElement result;
|
||||||
|
cron_timer_t T = { 0 };
|
||||||
|
jRead(argres, "", &result);
|
||||||
|
if (result.dataType == JREAD_ARRAY)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < result.elements; i++)
|
||||||
|
{
|
||||||
|
T.num = jRead_int(argres, "[*{'num'", &i);
|
||||||
|
T.del = jRead_int(argres, "[*{'del'", &i);
|
||||||
|
T.enab = jRead_int(argres, "[*{'enab'", &i);
|
||||||
|
T.prev = jRead_int(argres, "[*{'prev'", &i);
|
||||||
|
T.type = jRead_int(argres, "[*{'type'", &i);
|
||||||
|
T.sun_angle = (float) jRead_double(argres, "[*{'sun_angle'", &i);
|
||||||
|
jRead_string(argres, "[*{'name'", T.name, sizeof(T.name), &i);
|
||||||
|
jRead_string(argres, "[*{'cron'", T.cron, sizeof(T.cron), &i);
|
||||||
|
jRead_string(argres, "[*{'exec'", T.exec, sizeof(T.exec), &i);
|
||||||
|
|
||||||
|
if (T.type > 0)
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
int min = GetSunEvent((T.type == 1) ? 0 : 1, now, T.sun_angle);
|
||||||
|
sprintf(T.cron, "0 %d %d * * *", min % 60, min / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&GetSysConf()->Timers[T.num - 1], &T, sizeof(cron_timer_t));
|
||||||
|
}
|
||||||
|
ReloadCronSheduler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jWriteControl jwc;
|
||||||
|
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT);
|
||||||
|
for (int idx = 0; idx < CRON_TIMERS_NUMBER; idx++)
|
||||||
|
{
|
||||||
|
cron_timer_t T;
|
||||||
|
memcpy(&T, &GetSysConf()->Timers[idx], sizeof(cron_timer_t));
|
||||||
|
jwArr_object(&jwc);
|
||||||
|
jwObj_int(&jwc, "num", (unsigned int) T.num);
|
||||||
|
jwObj_int(&jwc, "del", (T.del) ? 1 : 0);
|
||||||
|
jwObj_int(&jwc, "enab", (T.enab) ? 1 : 0);
|
||||||
|
jwObj_int(&jwc, "prev", (T.prev) ? 1 : 0);
|
||||||
|
jwObj_int(&jwc, "type", (unsigned int) T.type);
|
||||||
|
jwObj_double(&jwc, "sun_angle", (double) T.sun_angle);
|
||||||
|
jwObj_string(&jwc, "name", T.name);
|
||||||
|
jwObj_string(&jwc, "cron", T.cron);
|
||||||
|
jwObj_string(&jwc, "exec", T.exec);
|
||||||
|
jwEnd(&jwc);
|
||||||
|
}
|
||||||
|
jwClose(&jwc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************ ASTRO *******************************/
|
||||||
|
|
||||||
|
#define C (3.14159265/180.0)
|
||||||
|
#define B (180.0/3.14159265)
|
||||||
|
#define zenith 90.8335f
|
||||||
|
|
||||||
|
#define LAT 54.73
|
||||||
|
#define LON 20.51
|
||||||
|
#define SUN_ANG 0
|
||||||
|
|
||||||
|
static uint16_t srTime = 0;
|
||||||
|
static uint16_t ssTime = 0;
|
||||||
|
|
||||||
|
static float Lat, Lon, Ang;
|
||||||
|
|
||||||
|
static int GetSunEvent(uint8_t event, uint32_t unixt, float ang);
|
||||||
|
|
||||||
|
uint16_t NumberDayFromUnix(uint32_t t)
|
||||||
|
{
|
||||||
|
time_t clock;
|
||||||
|
struct tm *tp;
|
||||||
|
clock = t;
|
||||||
|
tp = gmtime(&clock);
|
||||||
|
return ((uint16_t) tp->tm_yday) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSunConditions(double lat, double lon, double ang)
|
||||||
|
{
|
||||||
|
Lat = lat;
|
||||||
|
Lon = lon;
|
||||||
|
Ang = ang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSunTimes(uint32_t t)
|
||||||
|
{
|
||||||
|
double tt;
|
||||||
|
tt = GetSunEvent(0, t, SUN_ANG);
|
||||||
|
if (tt > 0)
|
||||||
|
srTime = tt;
|
||||||
|
else
|
||||||
|
srTime = 0xffff; //no valid sinrise time
|
||||||
|
tt = GetSunEvent(1, t, SUN_ANG);
|
||||||
|
if (tt > 0)
|
||||||
|
ssTime = tt;
|
||||||
|
else
|
||||||
|
ssTime = 0xffff; //no valid sunset time
|
||||||
|
|
||||||
|
ESP_LOGI("ASTRO", "Day number %d", NumberDayFromUnix(t));
|
||||||
|
ESP_LOGI("ASTRO", "Sanrise %dh %dm", srTime / 60 + 2, srTime - (srTime / 60 * 60));
|
||||||
|
ESP_LOGI("ASTRO", "Sanset %dh %dm", ssTime / 60 + 2, ssTime - (ssTime / 60 * 60));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t GetSunrise(void)
|
||||||
|
{
|
||||||
|
return srTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t GetSunset(void)
|
||||||
|
{
|
||||||
|
return ssTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetSunEvent(uint8_t event, uint32_t unixt, float ang)
|
||||||
|
{
|
||||||
|
float lngHour, t, M, L, RA, sinDec, cosDec, cosH, H, T, UT;
|
||||||
|
float Lquadrant, RAquadrant;
|
||||||
|
float zen;
|
||||||
|
int day = NumberDayFromUnix(unixt);
|
||||||
|
if (ang == 0)
|
||||||
|
zen = zenith + (float) ang; //sunrise/set
|
||||||
|
else
|
||||||
|
zen = 90.0 + (float) ang; //twilight
|
||||||
|
lngHour = GetSysConf()->sntpClient.lon / 15;
|
||||||
|
if (event == 0)
|
||||||
|
t = day + ((6 - lngHour) / 24);
|
||||||
|
else
|
||||||
|
t = day + ((18 - lngHour) / 24);
|
||||||
|
|
||||||
|
M = (0.9856 * t) - 3.289;
|
||||||
|
L = M + (1.916 * sin(M * C)) + (0.020 * sin(2 * M * C)) + 282.634;
|
||||||
|
if (L > 360)
|
||||||
|
{
|
||||||
|
L = L - 360;
|
||||||
|
}
|
||||||
|
else if (L < 0)
|
||||||
|
{
|
||||||
|
L = L + 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
RA = B * atan(0.91764 * tan(L * C));
|
||||||
|
if (RA > 360)
|
||||||
|
{
|
||||||
|
RA = RA - 360;
|
||||||
|
}
|
||||||
|
else if (RA < 0)
|
||||||
|
{
|
||||||
|
RA = RA + 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lquadrant = (floor(L / 90)) * 90;
|
||||||
|
RAquadrant = (floor(RA / 90)) * 90;
|
||||||
|
RA = RA + (Lquadrant - RAquadrant);
|
||||||
|
RA = RA / 15;
|
||||||
|
sinDec = 0.39782 * sin(L * C);
|
||||||
|
cosDec = cos(asin(sinDec));
|
||||||
|
cosH = (cos(zen * C) - (sinDec * sin(GetSysConf()->sntpClient.lat * C)))
|
||||||
|
/ (cosDec * cos(GetSysConf()->sntpClient.lat * C));
|
||||||
|
|
||||||
|
if (event == 0)
|
||||||
|
{ //rise
|
||||||
|
if (cosH > 1)
|
||||||
|
return -1;
|
||||||
|
H = 360 - B * (acos(cosH));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //set
|
||||||
|
if (cosH < -1)
|
||||||
|
return -1;
|
||||||
|
H = B * (acos(cosH));
|
||||||
|
}
|
||||||
|
|
||||||
|
H = H / 15;
|
||||||
|
T = H + RA - (0.06571 * t) - 6.622;
|
||||||
|
|
||||||
|
UT = T - lngHour;
|
||||||
|
|
||||||
|
if (UT >= 24)
|
||||||
|
{
|
||||||
|
UT = UT - 24;
|
||||||
|
}
|
||||||
|
else if (UT < 0)
|
||||||
|
{
|
||||||
|
UT = UT + 24;
|
||||||
|
}
|
||||||
|
return (int) floor(UT * 60.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int RecalcAstro(uint32_t tt)
|
||||||
|
{
|
||||||
|
struct timeval tv_now;
|
||||||
|
gettimeofday(&tv_now, NULL);
|
||||||
|
int timers_to_update = 0;
|
||||||
|
ESP_LOGI(TAG, "Recalculation astronomical events");
|
||||||
|
for (int i = 0; i < CRON_TIMERS_NUMBER; i++)
|
||||||
|
{
|
||||||
|
cron_timer_t *T = &GetSysConf()->Timers[i];
|
||||||
|
if (T->type == 0 || T->del)
|
||||||
|
continue;
|
||||||
|
int min = GetSunEvent((T->type == 1) ? 0 : 1, tt, T->sun_angle);
|
||||||
|
sprintf(T->cron, "0 %d %d * * *", min % 60, min / 60);
|
||||||
|
//ESP_LOGI(TAG, "Recalculated astro for rec %d new cron %s", T->num, T->cron);
|
||||||
|
++timers_to_update;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Recalculated %d astro timers", timers_to_update);
|
||||||
|
return timers_to_update;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MIDNIGHT_CHECK_INTERVAL 10
|
||||||
|
#define MIDNIGHT_DETECT_WINDOW 60
|
||||||
|
void MidnightTimer()
|
||||||
|
{
|
||||||
|
static int cnt = MIDNIGHT_CHECK_INTERVAL;
|
||||||
|
if (cnt-- <= 0)
|
||||||
|
{
|
||||||
|
cnt = MIDNIGHT_CHECK_INTERVAL;
|
||||||
|
struct timeval tv_now;
|
||||||
|
gettimeofday(&tv_now, NULL);
|
||||||
|
//ESP_LOGI(TAG, "Seconds remains to midnight %d", (int )tv_now.tv_sec % 86400);
|
||||||
|
if (tv_now.tv_sec % 86400 < MIDNIGHT_DETECT_WINDOW)
|
||||||
|
{
|
||||||
|
if (RecalcAstro(tv_now.tv_sec))
|
||||||
|
ReloadCronSheduler();
|
||||||
|
cnt = MIDNIGHT_CHECK_INTERVAL + MIDNIGHT_DETECT_WINDOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
155
src/EEPROM.c
Normal file
155
src/EEPROM.c
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
/* Copyright 2024 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 name: EEPROM.c
|
||||||
|
* Project: EVCHS_Stick
|
||||||
|
* Created on: 2024-06-20
|
||||||
|
* Author: bogd
|
||||||
|
* Description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webguiapp.h"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEBGUIAPP_I2C_ENABLE
|
||||||
|
|
||||||
|
#define TAG "EEPROMDriver"
|
||||||
|
|
||||||
|
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||||
|
#define I2C_MASTER_NUM CONFIG_I2C_HOST /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
||||||
|
#define I2C_MASTER_SDA_GPIO CONFIG_I2C_SDA_GPIO /*!< I2C master i2c SDA pin*/
|
||||||
|
#define I2C_MASTER_SCL_GPIO CONFIG_I2C_SCL_GPIO /*!< I2C master i2c SCL pin*/
|
||||||
|
|
||||||
|
#define EEPR24CXX_ADDR 0xA0 /*!< Slave address of 24Cxx devices*/
|
||||||
|
|
||||||
|
#define EEPROM_WRITE_PAGE_SIZE 32
|
||||||
|
#define EEPROM_WRITE_MAX_ATTEMPTS 20
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
i2c_port_t port; // I2C port number
|
||||||
|
uint8_t addr; // I2C address
|
||||||
|
uint32_t clk_speed; // I2C clock frequency for master mode
|
||||||
|
} i2c_dev_t;
|
||||||
|
|
||||||
|
i2c_dev_t eepr_24c32 = {
|
||||||
|
.port = I2C_MASTER_NUM,
|
||||||
|
.addr = EEPR24CXX_ADDR >> 1,
|
||||||
|
.clk_speed = CONFIG_I2C_CLOCK
|
||||||
|
};
|
||||||
|
|
||||||
|
static esp_err_t i2c_dev_read(const i2c_dev_t *dev, const void *out_data, size_t out_size, void *in_data,
|
||||||
|
size_t in_size)
|
||||||
|
{
|
||||||
|
if (!dev || !in_data || !in_size)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
if (out_data && out_size)
|
||||||
|
{
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (dev->addr << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
i2c_master_write(cmd, (void*) out_data, out_size, true);
|
||||||
|
}
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (dev->addr << 1) | 1, true);
|
||||||
|
i2c_master_read(cmd, in_data, in_size, I2C_MASTER_LAST_NACK);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
|
||||||
|
esp_err_t res = i2c_master_cmd_begin(dev->port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||||
|
/*
|
||||||
|
if (res != ESP_OK)
|
||||||
|
ESP_LOGE(TAG, "Could not read from device [0x%02x at %d]: %d", dev->addr, dev->port, res);
|
||||||
|
*/
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t i2c_dev_write(const i2c_dev_t *dev, const void *out_reg, size_t out_reg_size, const void *out_data,
|
||||||
|
size_t out_size)
|
||||||
|
{
|
||||||
|
if (!dev || !out_data || !out_size)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (dev->addr << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
if (out_reg && out_reg_size)
|
||||||
|
i2c_master_write(cmd, (void*) out_reg, out_reg_size, true);
|
||||||
|
i2c_master_write(cmd, (void*) out_data, out_size, true);
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
|
||||||
|
esp_err_t res = i2c_master_cmd_begin(dev->port, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
||||||
|
/*
|
||||||
|
if (res != ESP_OK)
|
||||||
|
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d", dev->addr, dev->port, res);
|
||||||
|
*/
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t eepr_i2c_read(uint16_t addr, uint8_t *data, int length)
|
||||||
|
{
|
||||||
|
|
||||||
|
int attempts = 0;
|
||||||
|
esp_err_t err;
|
||||||
|
uint8_t adr[] = { (uint8_t)(addr >> 8), (uint8_t)(addr & 0xff) };
|
||||||
|
while ((err = i2c_dev_read(&eepr_24c32, adr, 2, data, length)) != ESP_OK)
|
||||||
|
{
|
||||||
|
//ESP_LOGW(TAG, "EEPROM not ready attempt %d", attempts);
|
||||||
|
if (++attempts >= EEPROM_WRITE_MAX_ATTEMPTS) //Critical error
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "EEPROM read critical error!");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t eepr_i2c_write(uint16_t addr, uint8_t *data, int length)
|
||||||
|
{
|
||||||
|
int written = 0, attempts = 0;
|
||||||
|
uint16_t block_addr = addr;
|
||||||
|
esp_err_t err;
|
||||||
|
while ((length - written) > 0)
|
||||||
|
{
|
||||||
|
int block_len = MIN(length - written, EEPROM_WRITE_PAGE_SIZE);
|
||||||
|
uint8_t adr[] = { (uint8_t)(block_addr >> 8), (uint8_t)(block_addr & 0xff) };
|
||||||
|
while ((err = i2c_dev_write(&eepr_24c32, adr, 2, data + written, block_len)) != ESP_OK)
|
||||||
|
{
|
||||||
|
//ESP_LOGW(TAG, "EEPROM not ready attempt %d", attempts);
|
||||||
|
if (++attempts >= EEPROM_WRITE_MAX_ATTEMPTS) //Critical error
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "EEPROM write critical error!");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
attempts = 0;
|
||||||
|
written += block_len;
|
||||||
|
//ESP_LOGI(TAG, "written %d byte from addr %d", written, block_addr);
|
||||||
|
block_addr += EEPROM_WRITE_PAGE_SIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
391
src/FileBlockHandler.c
Normal file
391
src/FileBlockHandler.c
Normal file
|
|
@ -0,0 +1,391 @@
|
||||||
|
/* Copyright 2024 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 name: FileBlockHandler.c
|
||||||
|
* Project: WebguiappTemplate
|
||||||
|
* Created on: 2024-03-11
|
||||||
|
* Author: bogd
|
||||||
|
* Description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SystemApplication.h"
|
||||||
|
#include <SysConfiguration.h>
|
||||||
|
#include <webguiapp.h>
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
#include "mbedtls/base64.h"
|
||||||
|
|
||||||
|
#define TAG "RAW_MEM_API"
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"transid": 623787878,
|
||||||
|
"opertype" : 1, [1-READ, 2-DELETE, 3-WRITE]
|
||||||
|
"part": 0, []
|
||||||
|
"parts": 3, []
|
||||||
|
"mem_object": "testfile.txt", [Resource name string]
|
||||||
|
"size : 4096, [Data block size in bytes]
|
||||||
|
"dat" : "" , [Data block BASE64 encoded]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define READ_ORERATION 1
|
||||||
|
#define DELETE_ORERATION 2
|
||||||
|
#define WRITE_ORERATION 3
|
||||||
|
|
||||||
|
static cb_blockdata_transfer_t FileTransaction = {
|
||||||
|
.opertype = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_err_t ParseBlockDataObject(char *argres, cb_blockdata_transfer_t *ft)
|
||||||
|
{
|
||||||
|
struct jReadElement result;
|
||||||
|
jRead(argres, "", &result);
|
||||||
|
if (result.dataType != JREAD_OBJECT)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:not an object\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'transid'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
int trans = atoi((char*) result.pValue);
|
||||||
|
|
||||||
|
if (ft->open_file_timeout != 0)
|
||||||
|
{
|
||||||
|
if (trans != ft->transid)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Attempt second client access while first is not finished");
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"Device is busy, please try later\"");
|
||||||
|
return ESP_ERR_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ft->transid = trans;
|
||||||
|
//ESP_LOGI(TAG, "New transaction with id %d", ft->transid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'transid' not found, frontend update needed\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'opertype'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
ft->opertype = atoi((char*) result.pValue);
|
||||||
|
if (ft->opertype < 1 || ft->opertype > 3)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'operation' value not in [1...3]\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'operation' not found\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'parts'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
ft->parts = atoi((char*) result.pValue);
|
||||||
|
if (ft->parts < 0 || ft->parts > 20000)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'parts' value not in [0...20000]\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'parts' not found\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'part'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
ft->part = atoi((char*) result.pValue);
|
||||||
|
if (ft->parts < 0 || ft->part > ft->parts - 1)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'part' value not in [0...(parts-1)]\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'part' not found\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'mem_object'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
if (result.bytelen > 0 && result.bytelen < MEM_OBLECT_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
memcpy(ft->mem_object, (char*) result.pValue, result.bytelen);
|
||||||
|
ft->mem_object[result.bytelen] = 0x00;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'mem_object' length out of range\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'mem_object' not found\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
jRead(argres, "{'size'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
ft->size = atoi((char*) result.pValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'size' not found\"");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBlockHandler(char *argres, int rw, const char *path)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ParseBlockDataObject(argres, &FileTransaction) != ESP_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FileTransaction.open_file_timeout = BLOCK_OPERATION_TIMEOUT; //restart timeout on every block
|
||||||
|
|
||||||
|
//Phase of file operation calculate
|
||||||
|
FileTransaction.operphase = 0; //Simple read or write
|
||||||
|
if (FileTransaction.parts == 1)
|
||||||
|
FileTransaction.operphase = 3; //Only one block handle (open and close in one iteration)
|
||||||
|
else if (FileTransaction.part == 0)
|
||||||
|
FileTransaction.operphase = 1; //First block of multipart data (open file)
|
||||||
|
else if (FileTransaction.part == (FileTransaction.parts - 1))
|
||||||
|
FileTransaction.operphase = 2; //Last block of multipart data (close file)
|
||||||
|
|
||||||
|
strcpy(FileTransaction.filepath, path);
|
||||||
|
strcat(FileTransaction.filepath, FileTransaction.mem_object);
|
||||||
|
|
||||||
|
if (FileTransaction.operphase == 1 || FileTransaction.operphase == 3)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (FileTransaction.opertype == READ_ORERATION || FileTransaction.opertype == DELETE_ORERATION)
|
||||||
|
{
|
||||||
|
if (stat(FileTransaction.filepath, &FileTransaction.file_stat) == -1)
|
||||||
|
{
|
||||||
|
ESP_LOGE("FILE_API", "File does not exist : %s", FileTransaction.mem_object);
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
||||||
|
FileTransaction.open_file_timeout = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FileTransaction.opertype == WRITE_ORERATION)
|
||||||
|
{
|
||||||
|
if (stat(FileTransaction.filepath, &FileTransaction.file_stat) == 0)
|
||||||
|
{
|
||||||
|
if (unlink(FileTransaction.filepath) != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGE("FILE_API", "Delete file ERROR : %s", FileTransaction.mem_object);
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:File is already exists and can't be deleted\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileTransaction.opertype == DELETE_ORERATION)
|
||||||
|
{
|
||||||
|
unlink(FileTransaction.filepath);
|
||||||
|
FileTransaction.open_file_timeout = 0;
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"DELETED OK\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (FileTransaction.opertype == READ_ORERATION)
|
||||||
|
{
|
||||||
|
if (FileTransaction.operphase == 1 || FileTransaction.operphase == 3)
|
||||||
|
{
|
||||||
|
FileTransaction.f = fopen(FileTransaction.filepath, "r");
|
||||||
|
ESP_LOGI("FILE_API", "Open file for read : %s", FileTransaction.mem_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *scr, *dst;
|
||||||
|
size_t dlen, olen, slen;
|
||||||
|
if (FileTransaction.f == NULL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to open file %s for writing", FileTransaction.mem_object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scr = (unsigned char*) malloc(FileTransaction.size + 1);
|
||||||
|
if (scr == NULL)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR: no memory to handle request\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read = fread(scr, 1, FileTransaction.size, FileTransaction.f);
|
||||||
|
scr[read] = 0x00;
|
||||||
|
slen = read;
|
||||||
|
if (FileTransaction.operphase == 2 || FileTransaction.operphase == 3)
|
||||||
|
{
|
||||||
|
fclose(FileTransaction.f);
|
||||||
|
FileTransaction.f = NULL;
|
||||||
|
FileTransaction.open_file_timeout = 0;
|
||||||
|
ESP_LOGI("FILE_API", "Close file for read : %s", FileTransaction.mem_object);
|
||||||
|
}
|
||||||
|
dlen = 0;
|
||||||
|
mbedtls_base64_encode(NULL, dlen, &olen, scr, slen);
|
||||||
|
dst = (unsigned char*) malloc(olen);
|
||||||
|
dlen = olen;
|
||||||
|
mbedtls_base64_encode(dst, dlen, &olen, scr, slen);
|
||||||
|
|
||||||
|
struct jWriteControl jwc;
|
||||||
|
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_OBJECT, JW_COMPACT);
|
||||||
|
jwObj_int(&jwc, "transid", FileTransaction.transid);
|
||||||
|
jwObj_int(&jwc, "opertype", FileTransaction.opertype);
|
||||||
|
jwObj_int(&jwc, "parts", FileTransaction.parts);
|
||||||
|
jwObj_int(&jwc, "part", FileTransaction.part);
|
||||||
|
|
||||||
|
jwObj_string(&jwc, "mem_object", FileTransaction.mem_object);
|
||||||
|
jwObj_int(&jwc, "size", read);
|
||||||
|
jwObj_string(&jwc, "dat", (char*) dst);
|
||||||
|
jwClose(&jwc);
|
||||||
|
free(scr);
|
||||||
|
free(dst);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (FileTransaction.opertype == WRITE_ORERATION)
|
||||||
|
{
|
||||||
|
struct jReadElement result;
|
||||||
|
jRead(argres, "{'dat'", &result);
|
||||||
|
if (result.elements == 1)
|
||||||
|
{
|
||||||
|
if (result.bytelen > 0)
|
||||||
|
{
|
||||||
|
unsigned char *dst;
|
||||||
|
size_t dlen, olen;
|
||||||
|
if (FileTransaction.operphase == 1 || FileTransaction.operphase == 3)
|
||||||
|
{
|
||||||
|
FileTransaction.f = fopen(FileTransaction.filepath, "a");
|
||||||
|
ESP_LOGI("FILE_API", "Open file for write : %s", FileTransaction.mem_object);
|
||||||
|
}
|
||||||
|
if (FileTransaction.f == NULL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to open file %s for writing", FileTransaction.mem_object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dlen = 0;
|
||||||
|
mbedtls_base64_decode(NULL, dlen, &olen, (unsigned char*) result.pValue, (size_t) result.bytelen);
|
||||||
|
dst = (unsigned char*) malloc(olen);
|
||||||
|
dlen = olen;
|
||||||
|
mbedtls_base64_decode(dst, dlen, &olen, (unsigned char*) result.pValue, (size_t) result.bytelen);
|
||||||
|
//ESP_LOGI("FILE_API", "File write operation BEGIN");
|
||||||
|
int write = fwrite((char*) dst, olen, 1, FileTransaction.f);
|
||||||
|
//ESP_LOGI("FILE_API", "File write operation END");
|
||||||
|
if (FileTransaction.operphase == 2 || FileTransaction.operphase == 3)
|
||||||
|
{
|
||||||
|
fclose(FileTransaction.f);
|
||||||
|
FileTransaction.f = NULL;
|
||||||
|
FileTransaction.open_file_timeout = 0;
|
||||||
|
ESP_LOGI("FILE_API", "Close file for write : %s", FileTransaction.mem_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dst);
|
||||||
|
struct jWriteControl jwc;
|
||||||
|
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_OBJECT, JW_COMPACT);
|
||||||
|
jwObj_int(&jwc, "transid", FileTransaction.transid);
|
||||||
|
jwObj_int(&jwc, "opertype", FileTransaction.opertype);
|
||||||
|
jwObj_int(&jwc, "parts", FileTransaction.parts);
|
||||||
|
jwObj_int(&jwc, "part", FileTransaction.part);
|
||||||
|
jwObj_string(&jwc, "mem_object", FileTransaction.mem_object);
|
||||||
|
jwObj_int(&jwc, "size", write);
|
||||||
|
jwClose(&jwc);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'dat' length out of range\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'dat' not found\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBlockTimeoutCounter()
|
||||||
|
{
|
||||||
|
if (FileTransaction.open_file_timeout)
|
||||||
|
{
|
||||||
|
if (--FileTransaction.open_file_timeout == 0)
|
||||||
|
{
|
||||||
|
if (FileTransaction.f != NULL)
|
||||||
|
fclose(FileTransaction.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//ESP_LOGI(TAG, "Block timeout %d", FileTransaction.open_file_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileListHandler(char *argres, int rw, const char *path)
|
||||||
|
{
|
||||||
|
char entrypath[FILE_PATH_MAX];
|
||||||
|
char entrysize[16];
|
||||||
|
const char *entrytype = "file";
|
||||||
|
struct dirent *entry;
|
||||||
|
struct stat entry_stat;
|
||||||
|
DIR *dir = opendir(path);
|
||||||
|
const size_t dirpath_len = strlen(path);
|
||||||
|
strlcpy(entrypath, path, sizeof(entrypath));
|
||||||
|
|
||||||
|
if (!dir)
|
||||||
|
{
|
||||||
|
ESP_LOGE("FILE_API", "Failed to stat dir : %s", path);
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jWriteControl jwc;
|
||||||
|
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT);
|
||||||
|
while ((entry = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
|
||||||
|
entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
|
||||||
|
if (stat(entrypath, &entry_stat) == -1)
|
||||||
|
{
|
||||||
|
ESP_LOGE("FILE_API", "Failed to stat %s : %s", entrytype, entry->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
jwArr_object(&jwc);
|
||||||
|
jwObj_raw(&jwc, "sel", "false");
|
||||||
|
jwObj_string(&jwc, "name", (char*) entry->d_name);
|
||||||
|
jwObj_int(&jwc, "size", entry_stat.st_size);
|
||||||
|
jwEnd(&jwc);
|
||||||
|
}
|
||||||
|
jwClose(&jwc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -16,22 +16,22 @@
|
||||||
* Project: ChargePointMainboard
|
* Project: ChargePointMainboard
|
||||||
* Created on: 2022-07-21
|
* Created on: 2022-07-21
|
||||||
* Author: Bogdan Pilyugin
|
* Author: Bogdan Pilyugin
|
||||||
* Description:
|
* Description:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../include/SysConfiguration.h"
|
#include "../include/SysConfiguration.h"
|
||||||
|
#include "NetTransport.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_modem_api.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_ppp.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_netif.h"
|
|
||||||
#include "esp_netif_ppp.h"
|
|
||||||
#include "esp_event.h"
|
|
||||||
#include "esp_modem_api.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "NetTransport.h"
|
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||||
static EventGroupHandle_t event_group = NULL;
|
static EventGroupHandle_t event_group = NULL;
|
||||||
|
|
@ -41,306 +41,303 @@ static int ResetType = 0;
|
||||||
static bool isPPPinitializing = false;
|
static bool isPPPinitializing = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CUSTOM_MODEM_BAUDRATE 115200
|
||||||
|
|
||||||
|
#define MAX_COMMAND_REPEATE_NUMBER 15
|
||||||
|
#define WATCHDOG_INTERVAL 30
|
||||||
|
#define WAIT_FOR_GET_IP 30
|
||||||
|
|
||||||
static bool isPPPConn = false;
|
static bool isPPPConn = false;
|
||||||
static int attimeout = 1000;
|
static int attimeout = 1000;
|
||||||
TaskHandle_t initTaskhandle;
|
TaskHandle_t initTaskhandle;
|
||||||
|
|
||||||
#define PPP_MODEM_TIMEOUT 40
|
MODEM_INFO mod_info = {"-", "-", "-", "-"};
|
||||||
|
|
||||||
MODEM_INFO mod_info = { "-", "-", "-", "-" };
|
|
||||||
esp_netif_t *ppp_netif;
|
esp_netif_t *ppp_netif;
|
||||||
esp_modem_dce_t *dce;
|
esp_modem_dce_t *dce;
|
||||||
TaskHandle_t trasporttask;
|
TaskHandle_t trasporttask;
|
||||||
|
|
||||||
static void (*gsm_reset)(uint8_t level) = NULL;
|
static void (*gsm_reset)(uint8_t level) = NULL;
|
||||||
void RegGSMReset(void (*gsm_rst)(uint8_t level))
|
void RegGSMReset(void (*gsm_rst)(uint8_t level)) { gsm_reset = gsm_rst; }
|
||||||
{
|
|
||||||
gsm_reset = gsm_rst;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_netif_t* GetPPPNetifAdapter(void)
|
esp_netif_t *GetPPPNetifAdapter(void) {
|
||||||
{
|
if (isPPPConn)
|
||||||
return ppp_netif;
|
return ppp_netif;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MODEM_INFO* GetPPPModemInfo(void)
|
MODEM_INFO *GetPPPModemInfo(void) { return &mod_info; }
|
||||||
{
|
|
||||||
return &mod_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPPPConnected(void)
|
bool isPPPConnected(void) { return isPPPConn; }
|
||||||
{
|
|
||||||
return isPPPConn;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||||
int32_t event_id,
|
int32_t event_id, void *event_data) {
|
||||||
void *event_data)
|
ESP_LOGI(TAG, "PPP state changed event %u", (unsigned int)event_id);
|
||||||
{
|
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||||
ESP_LOGI(TAG, "PPP state changed event %u", (unsigned int )event_id);
|
/* User interrupted event from esp-netif */
|
||||||
if (event_id == NETIF_PPP_ERRORUSER)
|
esp_netif_t *netif = event_data;
|
||||||
{
|
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||||
/* User interrupted event from esp-netif */
|
}
|
||||||
esp_netif_t *netif = event_data;
|
|
||||||
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
static void on_ip_event(void *arg, esp_event_base_t event_base,
|
||||||
int32_t event_id,
|
int32_t event_id, void *event_data) {
|
||||||
void *event_data)
|
ESP_LOGD(TAG, "IP event! %u", (unsigned int)event_id);
|
||||||
{
|
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||||
ESP_LOGD(TAG, "IP event! %u", (unsigned int )event_id);
|
esp_netif_dns_info_t dns_info;
|
||||||
if (event_id == IP_EVENT_PPP_GOT_IP)
|
|
||||||
{
|
|
||||||
esp_netif_dns_info_t dns_info;
|
|
||||||
|
|
||||||
ip_event_got_ip_t *event = (ip_event_got_ip_t*) event_data;
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
esp_netif_t *netif = event->esp_netif;
|
esp_netif_t *netif = event->esp_netif;
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||||
memcpy(&GetSysConf()->gsmSettings.IPAddr, &event->ip_info.ip, sizeof(event->ip_info.ip));
|
memcpy(&GetSysConf()->gsmSettings.IPAddr, &event->ip_info.ip,
|
||||||
memcpy(&GetSysConf()->gsmSettings.Mask, &event->ip_info.netmask, sizeof(event->ip_info.netmask));
|
sizeof(event->ip_info.ip));
|
||||||
memcpy(&GetSysConf()->gsmSettings.Gateway, &event->ip_info.gw, sizeof(event->ip_info.gw));
|
memcpy(&GetSysConf()->gsmSettings.Mask, &event->ip_info.netmask,
|
||||||
|
sizeof(event->ip_info.netmask));
|
||||||
|
memcpy(&GetSysConf()->gsmSettings.Gateway, &event->ip_info.gw,
|
||||||
|
sizeof(event->ip_info.gw));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
|
||||||
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
|
||||||
esp_netif_get_dns_info(netif, 0, &dns_info);
|
esp_netif_get_dns_info(netif, 0, &dns_info);
|
||||||
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
esp_netif_get_dns_info(netif, 1, &dns_info);
|
esp_netif_get_dns_info(netif, 1, &dns_info);
|
||||||
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
|
||||||
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
|
||||||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||||
isPPPConn = true;
|
isPPPConn = true;
|
||||||
ESP_LOGI(TAG, "GOT ip event!!!");
|
ESP_LOGI(TAG, "GOT ip event!!!");
|
||||||
}
|
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||||
else if (event_id == IP_EVENT_PPP_LOST_IP)
|
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
||||||
{
|
isPPPConn = false;
|
||||||
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
|
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||||
isPPPConn = false;
|
ESP_LOGI(TAG, "GOT IPv6 event!");
|
||||||
}
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
|
||||||
else if (event_id == IP_EVENT_GOT_IP6)
|
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||||
{
|
}
|
||||||
ESP_LOGI(TAG, "GOT IPv6 event!");
|
|
||||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t*) event_data;
|
|
||||||
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemNotReady(void)
|
void ModemNotReady(void) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
static void GSMInitTask(void *pvParameter) {
|
||||||
|
isPPPinitializing = true;
|
||||||
|
int starttype = *((int *)pvParameter);
|
||||||
|
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event);
|
||||||
|
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID,
|
||||||
|
&on_ppp_changed);
|
||||||
|
|
||||||
static void GSMInitTask(void *pvParameter)
|
if (dce) {
|
||||||
{
|
esp_modem_destroy(dce);
|
||||||
isPPPinitializing = true;
|
}
|
||||||
int starttype = *((int*) pvParameter);
|
|
||||||
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event);
|
|
||||||
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed);
|
|
||||||
|
|
||||||
if (dce)
|
if (ppp_netif != NULL) {
|
||||||
{
|
esp_netif_destroy(ppp_netif);
|
||||||
esp_modem_destroy(dce);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ppp_netif != NULL)
|
if (starttype == 0) {
|
||||||
{
|
ESP_LOGE(TAG, "GSM module power down and up reset");
|
||||||
esp_netif_destroy(ppp_netif);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (starttype == 0)
|
|
||||||
{
|
|
||||||
#if CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN >= 0
|
#if CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN >= 0
|
||||||
gpio_set_level(CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN, 0);
|
gpio_set_level(CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN, 0);
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
gpio_set_level(CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN, 1);
|
gpio_set_level(CONFIG_MODEM_DEVICE_POWER_CONTROL_PIN, 1);
|
||||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
#else
|
#else
|
||||||
if (gsm_reset)
|
if (gsm_reset) {
|
||||||
{
|
gsm_reset(0);
|
||||||
gsm_reset(0);
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
gsm_reset(1);
|
||||||
gsm_reset(1);
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
}
|
} else {
|
||||||
else
|
ESP_LOGE(TAG, "GSM module reset procedure not defined");
|
||||||
{
|
ESP_ERROR_CHECK(1);
|
||||||
ESP_LOGE(TAG, "ethernet chip reset pin not defined");
|
}
|
||||||
ESP_ERROR_CHECK(1);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID,
|
||||||
|
&on_ip_event, NULL));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID,
|
||||||
|
&on_ppp_changed, NULL));
|
||||||
|
event_group = xEventGroupCreate();
|
||||||
|
/* Configure the DTE */
|
||||||
|
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||||
|
/* setup UART specific configuration based on kconfig options */
|
||||||
|
dte_config.uart_config.port_num = CONFIG_MODEM_UART_PORT_NUM;
|
||||||
|
dte_config.uart_config.tx_io_num = CONFIG_MODEM_UART_TX_PIN;
|
||||||
|
dte_config.uart_config.rx_io_num = CONFIG_MODEM_UART_RX_PIN;
|
||||||
|
dte_config.uart_config.rts_io_num = CONFIG_MODEM_UART_RTS_PIN;
|
||||||
|
dte_config.uart_config.cts_io_num = CONFIG_MODEM_UART_CTS_PIN;
|
||||||
|
dte_config.uart_config.rx_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE;
|
||||||
|
dte_config.uart_config.tx_buffer_size = CONFIG_MODEM_UART_TX_BUFFER_SIZE;
|
||||||
|
dte_config.uart_config.event_queue_size = CONFIG_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||||
|
dte_config.task_stack_size = CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||||
|
dte_config.task_priority = CONFIG_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||||
|
dte_config.dte_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||||
|
/* Configure the DCE */
|
||||||
|
esp_modem_dce_config_t dce_config =
|
||||||
|
ESP_MODEM_DCE_DEFAULT_CONFIG(GetSysConf()->gsmSettings.APN);
|
||||||
|
/* Configure the PPP netif */
|
||||||
|
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_PPP();
|
||||||
|
|
||||||
|
esp_netif_conf.route_prio = PPP_PRIO;
|
||||||
|
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||||
|
|
||||||
|
netif_ppp_config.base = &esp_netif_conf;
|
||||||
|
|
||||||
|
/* Init netif object */
|
||||||
|
ppp_netif = esp_netif_new(&netif_ppp_config);
|
||||||
|
assert(ppp_netif);
|
||||||
|
dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config,
|
||||||
|
ppp_netif);
|
||||||
|
assert(dce);
|
||||||
|
|
||||||
|
if (esp_modem_set_baud(dce, CUSTOM_MODEM_BAUDRATE) == ESP_OK)
|
||||||
|
uart_set_baudrate(0, CUSTOM_MODEM_BAUDRATE);
|
||||||
|
|
||||||
|
mod_info.model[0] = 0x00;
|
||||||
|
|
||||||
|
int OperationRepeate = 0;
|
||||||
|
// MODULE NAME
|
||||||
|
while (esp_modem_get_module_name(dce, mod_info.model) != ESP_OK) {
|
||||||
|
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||||
|
ESP_LOGE(TAG, "Error get module name");
|
||||||
|
goto modem_init_fail;
|
||||||
}
|
}
|
||||||
|
ESP_LOGW(TAG, "Retry get module name");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Module type:%s", mod_info.model);
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
|
// IMSI
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
|
OperationRepeate = 0;
|
||||||
event_group = xEventGroupCreate();
|
mod_info.imsi[0] = 0x00;
|
||||||
/* Configure the DTE */
|
while (esp_modem_get_imsi(dce, mod_info.imsi) != ESP_OK) {
|
||||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||||
/* setup UART specific configuration based on kconfig options */
|
ESP_LOGE(TAG, "Error get IMSI");
|
||||||
dte_config.uart_config.port_num = CONFIG_MODEM_UART_PORT_NUM;
|
goto modem_init_fail;
|
||||||
dte_config.uart_config.tx_io_num = CONFIG_MODEM_UART_TX_PIN;
|
|
||||||
dte_config.uart_config.rx_io_num = CONFIG_MODEM_UART_RX_PIN;
|
|
||||||
dte_config.uart_config.rts_io_num = CONFIG_MODEM_UART_RTS_PIN;
|
|
||||||
dte_config.uart_config.cts_io_num = CONFIG_MODEM_UART_CTS_PIN;
|
|
||||||
dte_config.uart_config.rx_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE;
|
|
||||||
dte_config.uart_config.tx_buffer_size = CONFIG_MODEM_UART_TX_BUFFER_SIZE;
|
|
||||||
dte_config.uart_config.event_queue_size = CONFIG_MODEM_UART_EVENT_QUEUE_SIZE;
|
|
||||||
dte_config.task_stack_size = CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
|
||||||
dte_config.task_priority = CONFIG_MODEM_UART_EVENT_TASK_PRIORITY;
|
|
||||||
dte_config.dte_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE / 2;
|
|
||||||
/* Configure the DCE */
|
|
||||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(GetSysConf()->gsmSettings.APN);
|
|
||||||
/* Configure the PPP netif */
|
|
||||||
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_PPP();
|
|
||||||
|
|
||||||
esp_netif_conf.route_prio = PPP_PRIO;
|
|
||||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
|
||||||
|
|
||||||
netif_ppp_config.base = &esp_netif_conf;
|
|
||||||
|
|
||||||
/* Init netif object */
|
|
||||||
ppp_netif = esp_netif_new(&netif_ppp_config);
|
|
||||||
assert(ppp_netif);
|
|
||||||
dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, ppp_netif);
|
|
||||||
assert(dce);
|
|
||||||
|
|
||||||
mod_info.model[0] = 0x00;
|
|
||||||
int GSMConnectTimeout = 0;
|
|
||||||
while (esp_modem_get_module_name(dce, mod_info.model) != ESP_OK)
|
|
||||||
{
|
|
||||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
|
||||||
goto modem_init_fail;
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Module type:%s", mod_info.model);
|
ESP_LOGW(TAG, "Retry get IMSI");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "IMSI:%s", mod_info.imsi);
|
||||||
|
|
||||||
mod_info.imsi[0] = 0x00;
|
// OPERATOR NAME
|
||||||
while (esp_modem_get_imsi(dce, mod_info.imsi) != ESP_OK)
|
OperationRepeate = 0;
|
||||||
{
|
mod_info.oper[0] = 0x00;
|
||||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
int tech = 0;
|
||||||
goto modem_init_fail;
|
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
while (esp_modem_get_operator_name(dce, mod_info.oper, &tech) != ESP_OK) {
|
||||||
|
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||||
|
ESP_LOGE(TAG, "Error get operator name");
|
||||||
|
goto modem_init_fail;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "IMSI:%s", mod_info.imsi);
|
ESP_LOGW(TAG, "Retry get operator name");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Operator:%s", mod_info.oper);
|
||||||
|
|
||||||
mod_info.oper[0] = 0x00;
|
// IMEI
|
||||||
int tech = 0;
|
mod_info.imei[0] = 0x00;
|
||||||
while (esp_modem_get_operator_name(dce, mod_info.oper, &tech) != ESP_OK)
|
OperationRepeate = 0;
|
||||||
{
|
while (esp_modem_get_imei(dce, mod_info.imei) != ESP_OK) {
|
||||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||||
goto modem_init_fail;
|
ESP_LOGE(TAG, "Error get IMEI");
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
goto modem_init_fail;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Operator:%s", mod_info.oper);
|
ESP_LOGW(TAG, "Retry get IMEI");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "IMEI:%s", mod_info.imei);
|
||||||
|
|
||||||
mod_info.imei[0] = 0x00;
|
// SWITCH TO CMUX
|
||||||
while (esp_modem_get_imei(dce, mod_info.imei) != ESP_OK)
|
OperationRepeate = 0;
|
||||||
{
|
while (esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX) != ESP_OK) {
|
||||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||||
goto modem_init_fail;
|
ESP_LOGE(TAG, "Error switch module to CMUX");
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
goto modem_init_fail;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "IMEI:%s", mod_info.imei);
|
ESP_LOGW(TAG, "Retry switch module to CMUX");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
while (esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX) != ESP_OK)
|
ESP_LOGI(TAG, "PPP data mode OK");
|
||||||
{
|
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(WAIT_FOR_GET_IP * 1000));
|
||||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
|
||||||
goto modem_init_fail;
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "PPP data mode OK");
|
isPPPinitializing = false;
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
|
||||||
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
return;
|
||||||
|
|
||||||
isPPPinitializing = false;
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
|
|
||||||
return;
|
|
||||||
modem_init_fail:
|
modem_init_fail:
|
||||||
ESP_LOGE(TAG, "PPP modem init error");
|
ESP_LOGE(TAG, "PPP modem initialization fail");
|
||||||
isPPPinitializing = false;
|
isPPPinitializing = false;
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPPModemColdStart(void)
|
void PPPModemColdStart(void) {
|
||||||
{
|
ResetType = 0;
|
||||||
ResetType = 0;
|
xTaskCreatePinnedToCore(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3,
|
||||||
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
|
&initTaskhandle, 1);
|
||||||
|
ESP_LOGI(TAG, "Start GSM cold initialization task");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPPModemSoftRestart(void)
|
void PPPModemSoftRestart(void) {
|
||||||
{
|
ResetType = 1;
|
||||||
ResetType = 1;
|
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3,
|
||||||
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
|
&initTaskhandle);
|
||||||
|
ESP_LOGI(TAG, "Start GSM soft initialization task");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GSMRunTask(void *pvParameter)
|
static void GSMRunTask(void *pvParameter) {
|
||||||
{
|
while (1) {
|
||||||
while (1)
|
if (!isPPPConn && !isPPPinitializing) { // try to reconnect modem
|
||||||
{
|
ESP_LOGW(TAG, "Module restart by watchdog");
|
||||||
if (!isPPPConn && !isPPPinitializing)
|
PPPModemColdStart();
|
||||||
{ //try to reconnect modem
|
|
||||||
ESP_LOGI(TAG, "PPP modem restart");
|
|
||||||
PPPModemColdStart();
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(30000));
|
|
||||||
}
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(WATCHDOG_INTERVAL * 1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPPModemStart(void)
|
void PPPModemStart(void) {
|
||||||
{
|
xTaskCreatePinnedToCore(GSMRunTask, "GSMRunTask", 1024 * 4, &ResetType, 3, NULL, 1);
|
||||||
xTaskCreate(GSMRunTask, "GSMRunTask", 1024 * 4, &ResetType, 3, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PPPModemGetRSSI(void)
|
int PPPModemGetRSSI(void) {
|
||||||
{
|
int rssi = -1, ber;
|
||||||
int rssi = -1, ber;
|
if (isPPPConn)
|
||||||
esp_modem_get_signal_quality(dce, &rssi, &ber);
|
esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||||
return rssi;
|
return rssi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemSetATTimeout(int timeout)
|
void ModemSetATTimeout(int timeout) { attimeout = timeout; }
|
||||||
{
|
|
||||||
attimeout = timeout;
|
void ModemSendAT(char *cmd, char *resp, int timeout) {
|
||||||
|
ESP_LOGI(TAG, "Command:%s", cmd);
|
||||||
|
int res = esp_modem_at(dce, cmd, resp, attimeout);
|
||||||
|
switch (res) {
|
||||||
|
case 0:
|
||||||
|
ESP_LOGI(TAG, "OK");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ESP_LOGE(TAG, "FAIL");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ESP_LOGE(TAG, "TIMEOUT");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Response:%s", resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemSendAT(char *cmd, char *resp, int timeout)
|
esp_err_t cmd_cb(uint8_t *data, int len) {
|
||||||
{
|
ESP_LOGI(TAG, "Response:%*s", len, data);
|
||||||
ESP_LOGI(TAG, "Command:%s", cmd);
|
return ESP_OK;
|
||||||
int res = esp_modem_at(dce, cmd, resp, attimeout);
|
|
||||||
switch(res)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
ESP_LOGI(TAG, "OK");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ESP_LOGE(TAG, "FAIL");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ESP_LOGE(TAG, "TIMEOUT");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Response:%s", resp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t cmd_cb(uint8_t* data, int len)
|
void ModemSendSMS(void) { esp_modem_command(dce, "atd", &cmd_cb, 3000); }
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Response:%*s", len, data);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModemSendSMS(void)
|
|
||||||
{
|
|
||||||
esp_modem_command(dce, "atd", &cmd_cb, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,19 +57,24 @@ void regHTTPUserAppHandlers(char *url,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BASIC_LOGIN_LENGTH 31
|
||||||
|
#define BASIC_PASS_LENGTH 31
|
||||||
|
#define BASIC_DECODED_LENGTH (BASIC_LOGIN_LENGTH + BASIC_PASS_LENGTH + 1 + 1)
|
||||||
|
#define BASIC_ENCODED_LENGTH (BASIC_DECODED_LENGTH * 4 / 3)
|
||||||
|
|
||||||
static esp_err_t CheckAuth(httpd_req_t *req)
|
static esp_err_t CheckAuth(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
unsigned char pass[18] = { 0 }; //max length of login:password decoded string
|
unsigned char pass[BASIC_DECODED_LENGTH] = { 0 }; //max length of login:password decoded string
|
||||||
unsigned char inp[31]; //max length of login:password coded string plus Basic
|
unsigned char inp[BASIC_ENCODED_LENGTH]; //max length of login:password coded string plus Basic
|
||||||
const char keyword1[] = "Basic ";
|
const char keyword1[] = "Basic ";
|
||||||
const int keyword1len = sizeof(keyword1) - 1;
|
const int keyword1len = sizeof(keyword1) - 1;
|
||||||
if (httpd_req_get_hdr_value_len(req, "Authorization") > 31)
|
if (httpd_req_get_hdr_value_len(req, "Authorization") > BASIC_ENCODED_LENGTH)
|
||||||
{
|
{
|
||||||
httpd_resp_set_hdr(req, "Connection", "close");
|
httpd_resp_set_hdr(req, "Connection", "close");
|
||||||
httpd_resp_send_err(req, HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE, "Authorization field value is too large");
|
httpd_resp_send_err(req, HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE, "Authorization field value is too large");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
httpd_req_get_hdr_value_str(req, "Authorization", (char*) inp, 31);
|
httpd_req_get_hdr_value_str(req, "Authorization", (char*) inp, BASIC_ENCODED_LENGTH);
|
||||||
unsigned char *pt = memmem(inp, sizeof(inp), keyword1, keyword1len);
|
unsigned char *pt = memmem(inp, sizeof(inp), keyword1, keyword1len);
|
||||||
if (pt)
|
if (pt)
|
||||||
{
|
{
|
||||||
|
|
@ -460,7 +465,11 @@ esp_err_t start_file_server(void)
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
strlcpy(server_data->base_path, "/", sizeof("/"));
|
strlcpy(server_data->base_path, "/", sizeof("/"));
|
||||||
|
#if CONFIG_SDCARD_ENABLE
|
||||||
|
strlcpy(server_data->base_path2, "/sdcard", sizeof("/sdcard"));
|
||||||
|
#else
|
||||||
strlcpy(server_data->base_path2, "/data", sizeof("/data"));
|
strlcpy(server_data->base_path2, "/data", sizeof("/data"));
|
||||||
|
#endif
|
||||||
server = start_webserver();
|
server = start_webserver();
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
src/MQTT.c
33
src/MQTT.c
|
|
@ -28,17 +28,13 @@
|
||||||
|
|
||||||
#define TAG "MQTT"
|
#define TAG "MQTT"
|
||||||
#define SERVICE_NAME "SYSTEM" // Dedicated service name
|
#define SERVICE_NAME "SYSTEM" // Dedicated service name
|
||||||
#define FILE_SERVICE_NAME "FILE"
|
|
||||||
#define EXTERNAL_SERVICE_NAME "RS485"
|
|
||||||
#define UPLINK_SUBTOPIC "UPLINK" // Device publish to this topic
|
|
||||||
#define DOWNLINK_SUBTOPIC "DWLINK" // Device listen from this topic
|
|
||||||
|
|
||||||
#define MQTT_DEBUG_MODE CONFIG_WEBGUIAPP_MQTT_DEBUG_LEVEL
|
#define MQTT_DEBUG_MODE CONFIG_WEBGUIAPP_MQTT_DEBUG_LEVEL
|
||||||
|
|
||||||
#define MQTT_MESSAGE_BUFER_LENTH 10 //size of mqtt queue
|
#define MQTT_MESSAGE_BUFER_LENTH 10 //size of mqtt queue
|
||||||
#define MQTT_RECONNECT_CHANGE_ADAPTER 3
|
#define MQTT_RECONNECT_CHANGE_ADAPTER 3
|
||||||
|
|
||||||
#define MQTT_RECONNECT_TIMEOUT 20
|
#define MQTT_RECONNECT_TIMEOUT 10
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
||||||
|
|
||||||
|
|
@ -107,8 +103,8 @@ void ComposeTopic(char *topic, int idx, char *service_name, char *direct)
|
||||||
strcat((char*) topic, GetSysConf()->mqttStation[idx].GroupName); // Global system name
|
strcat((char*) topic, GetSysConf()->mqttStation[idx].GroupName); // Global system name
|
||||||
strcat((char*) topic, "/");
|
strcat((char*) topic, "/");
|
||||||
strcat((char*) topic, GetSysConf()->mqttStation[idx].ClientID); // Device client name (for multiclient devices)
|
strcat((char*) topic, GetSysConf()->mqttStation[idx].ClientID); // Device client name (for multiclient devices)
|
||||||
strcat((char*) topic, "-");
|
//strcat((char*) topic, "-");
|
||||||
strcat((char*) topic, GetSysConf()->ID); //
|
//strcat((char*) topic, GetSysConf()->ID); //
|
||||||
strcat((char*) topic, "/");
|
strcat((char*) topic, "/");
|
||||||
strcat((char*) topic, (const char*) service_name); // Device service name
|
strcat((char*) topic, (const char*) service_name); // Device service name
|
||||||
strcat((char*) topic, "/");
|
strcat((char*) topic, "/");
|
||||||
|
|
@ -127,6 +123,7 @@ esp_err_t SysServiceMQTTSend(char *data, int len, int idx)
|
||||||
ComposeTopic(DSS.topic, idx, SERVICE_NAME, UPLINK_SUBTOPIC);
|
ComposeTopic(DSS.topic, idx, SERVICE_NAME, UPLINK_SUBTOPIC);
|
||||||
DSS.raw_data_ptr = buf;
|
DSS.raw_data_ptr = buf;
|
||||||
DSS.data_length = len;
|
DSS.data_length = len;
|
||||||
|
DSS.keep_memory_onfinish = false;
|
||||||
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(0)) == pdPASS)
|
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(0)) == pdPASS)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
else
|
else
|
||||||
|
|
@ -221,13 +218,6 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
|
||||||
ESP_LOGI(TAG, "Subscribe to %s", topic);
|
ESP_LOGI(TAG, "Subscribe to %s", topic);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ComposeTopic(topic, idx, FILE_SERVICE_NAME, DOWNLINK_SUBTOPIC);
|
|
||||||
msg_id = esp_mqtt_client_subscribe(client, (char*) topic, 0);
|
|
||||||
#if MQTT_DEBUG_MODE > 0
|
|
||||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
|
||||||
ESP_LOGI(TAG, "Subscribe to %s", topic);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
||||||
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -273,7 +263,9 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
|
||||||
case MQTT_EVENT_DATA:
|
case MQTT_EVENT_DATA:
|
||||||
|
|
||||||
#if MQTT_DEBUG_MODE > 1
|
#if MQTT_DEBUG_MODE > 1
|
||||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA, client %d", idx);
|
ESP_LOGI(TAG, "MQTT_EVENT_DATA, client:%d, data-length:%d, offset:%d ", idx, event->data_len, event->current_data_offset);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "MQTT client %d data received:%.*s", idx, event->data_len, event->data);
|
||||||
#endif
|
#endif
|
||||||
if (event->data_len == 0 || event->current_data_offset > 0) //possible fragments of long data
|
if (event->data_len == 0 || event->current_data_offset > 0) //possible fragments of long data
|
||||||
goto end_of_system_handler;
|
goto end_of_system_handler;
|
||||||
|
|
@ -302,13 +294,6 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
|
||||||
ESP_LOGE(TAG, "Out of free RAM for MQTT API handle");
|
ESP_LOGE(TAG, "Out of free RAM for MQTT API handle");
|
||||||
}
|
}
|
||||||
|
|
||||||
ComposeTopic(topic, idx, FILE_SERVICE_NAME, DOWNLINK_SUBTOPIC);
|
|
||||||
if (!memcmp(topic, event->topic, event->topic_len))
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Got data for FILE_SYSTEM_SERVICE:%s", event->data);
|
|
||||||
//Here handler of file system operations
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
||||||
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -406,7 +391,7 @@ void MQTTTaskTransmit(void *pvParameter)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if MQTT_DEBUG_MODE > 1
|
#if MQTT_DEBUG_MODE > 1
|
||||||
ESP_LOGI(TAG, "MQTT client %d data send:%.*s", idx, DSS.data_length, DSS.raw_data_ptr);
|
ESP_LOGW(TAG, "MQTT client %d data send:%.*s", idx, DSS.data_length, DSS.raw_data_ptr);
|
||||||
#endif
|
#endif
|
||||||
esp_mqtt_client_publish(mqtt[idx].mqtt,
|
esp_mqtt_client_publish(mqtt[idx].mqtt,
|
||||||
(const char*) DSS.topic,
|
(const char*) DSS.topic,
|
||||||
|
|
@ -467,7 +452,7 @@ static void start_mqtt()
|
||||||
esp_mqtt_client_register_event(mqtt[i].mqtt, ESP_EVENT_ANY_ID, mqtt[i].user_event_handler, &mqtt[i]);
|
esp_mqtt_client_register_event(mqtt[i].mqtt, ESP_EVENT_ANY_ID, mqtt[i].user_event_handler, &mqtt[i]);
|
||||||
esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &reconnect_MQTT_handler, &mqtt[i].mqtt);
|
esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &reconnect_MQTT_handler, &mqtt[i].mqtt);
|
||||||
esp_mqtt_client_start(mqtt[i].mqtt);
|
esp_mqtt_client_start(mqtt[i].mqtt);
|
||||||
xTaskCreate(MQTTTaskTransmit, "MQTTTaskTransmit", 1024 * 2, (void*) &mqtt[i].mqtt_index, 3, NULL);
|
xTaskCreate(MQTTTaskTransmit, "MQTTTaskTransmit", 1024 * 4, (void*) &mqtt[i].mqtt_index, 3, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
214
src/RawMemAPI.c
214
src/RawMemAPI.c
|
|
@ -1,214 +0,0 @@
|
||||||
/* Copyright 2024 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 name: RawMemAPI.c
|
|
||||||
* Project: WebguiappTemplate
|
|
||||||
* Created on: 2024-03-11
|
|
||||||
* Author: bogd
|
|
||||||
* Description:
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "RawMemAPI.h"
|
|
||||||
#include "SystemApplication.h"
|
|
||||||
#include <SysConfiguration.h>
|
|
||||||
#include <webguiapp.h>
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "mbedtls/base64.h"
|
|
||||||
|
|
||||||
#define TAG "RAW_MEM_API"
|
|
||||||
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"operation" : 1,
|
|
||||||
"mem_object": "testfile.txt",
|
|
||||||
"offset" : 2000,
|
|
||||||
"size : 4096,
|
|
||||||
"data" : "" ,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define READ_ORERATION 1
|
|
||||||
#define DELETE_ORERATION 2
|
|
||||||
#define APPEND_ORERATION 3
|
|
||||||
#define REPLACE_ORERATION 4
|
|
||||||
|
|
||||||
static const char *dirpath = "/data/";
|
|
||||||
#define MEM_OBLECT_MAX_LENGTH 32
|
|
||||||
|
|
||||||
void RawDataHandler(char *argres, int rw)
|
|
||||||
{
|
|
||||||
int operation = 0;
|
|
||||||
int offset;
|
|
||||||
int size;
|
|
||||||
char mem_object[MEM_OBLECT_MAX_LENGTH];
|
|
||||||
char filepath[FILE_PATH_MAX];
|
|
||||||
struct stat file_stat;
|
|
||||||
|
|
||||||
struct jReadElement result;
|
|
||||||
jRead(argres, "", &result);
|
|
||||||
if (result.dataType != JREAD_OBJECT)
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:not an object\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jRead(argres, "{'operation'", &result);
|
|
||||||
if (result.elements == 1)
|
|
||||||
{
|
|
||||||
operation = atoi((char*) result.pValue);
|
|
||||||
if (operation < 1 || operation > 2)
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'operation' value not in [1...2]\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'operation' not found\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jRead(argres, "{'mem_object'", &result);
|
|
||||||
if (result.elements == 1)
|
|
||||||
{
|
|
||||||
if (result.bytelen > 0 && result.bytelen < MEM_OBLECT_MAX_LENGTH)
|
|
||||||
{
|
|
||||||
memcpy(mem_object, (char*) result.pValue, result.bytelen);
|
|
||||||
mem_object[result.bytelen] = 0x00;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'mem_object' length out of range\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'mem_object' not found\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jRead(argres, "{'offset'", &result);
|
|
||||||
if (result.elements == 1)
|
|
||||||
{
|
|
||||||
offset = atoi((char*) result.pValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'offset' not found\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jRead(argres, "{'size'", &result);
|
|
||||||
if (result.elements == 1)
|
|
||||||
{
|
|
||||||
size = atoi((char*) result.pValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'size' not found\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//ESP_LOGI(TAG, "Got memory object %s, with offest %d and size %d", mem_object, offset, size);
|
|
||||||
|
|
||||||
strcpy(filepath, dirpath);
|
|
||||||
strcat(filepath, mem_object);
|
|
||||||
|
|
||||||
if (stat(filepath, &file_stat) == -1)
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "File does not exist : %s", mem_object);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operation == DELETE_ORERATION)
|
|
||||||
{
|
|
||||||
unlink(filepath);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"DELETED OK\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (operation == READ_ORERATION)
|
|
||||||
{
|
|
||||||
FILE *f = fopen(filepath, "r");
|
|
||||||
if (f == NULL)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Failed to open file %s for writing", mem_object);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char *dat = (char*) malloc(size + 1);
|
|
||||||
if (dat == NULL)
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR: no memory to handle request\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fseek(f, offset, SEEK_SET);
|
|
||||||
int read = fread(dat, 1, size, f);
|
|
||||||
dat[read] = 0x00;
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
struct jWriteControl jwc;
|
|
||||||
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_OBJECT, JW_COMPACT);
|
|
||||||
jwObj_int(&jwc, "operation", operation);
|
|
||||||
jwObj_string(&jwc, "mem_object", mem_object);
|
|
||||||
jwObj_int(&jwc, "offset", offset);
|
|
||||||
jwObj_int(&jwc, "size", read);
|
|
||||||
jwObj_string(&jwc, "dat", dat);
|
|
||||||
jwClose(&jwc);
|
|
||||||
free(dat);
|
|
||||||
}
|
|
||||||
else if (operation == APPEND_ORERATION || operation == REPLACE_ORERATION)
|
|
||||||
{
|
|
||||||
jRead(argres, "{'dat'", &result);
|
|
||||||
if (result.elements == 1)
|
|
||||||
{
|
|
||||||
if (result.bytelen > 0 && result.bytelen <= size)
|
|
||||||
{
|
|
||||||
//memcpy(mem_object, (char*) result.pValue, result.bytelen);
|
|
||||||
//mem_object[result.bytelen] = 0x00;
|
|
||||||
if (operation == REPLACE_ORERATION)
|
|
||||||
FILE *f = fopen(filepath, "w");
|
|
||||||
else if (operation == APPEND_ORERATION)
|
|
||||||
FILE *f = fopen(filepath, "a");
|
|
||||||
|
|
||||||
if (f == NULL)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "Failed to open file %s for writing", mem_object);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fseek(f, offset, SEEK_SET);
|
|
||||||
int write = fwrite((char*) result.pValue, result.bytelen, 1, f);
|
|
||||||
struct jWriteControl jwc;
|
|
||||||
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_OBJECT, JW_COMPACT);
|
|
||||||
jwObj_int(&jwc, "operation", operation);
|
|
||||||
jwObj_string(&jwc, "mem_object", mem_object);
|
|
||||||
jwObj_int(&jwc, "offset", offset);
|
|
||||||
jwObj_int(&jwc, "size", write);
|
|
||||||
jwClose(&jwc);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:'dat' length out of range\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:key 'dat' not found\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
#include "esp_idf_version.h"
|
#include "esp_idf_version.h"
|
||||||
#include "NetTransport.h"
|
#include "NetTransport.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
#include "RawMemAPI.h"
|
|
||||||
|
|
||||||
extern SYS_CONFIG SysConfig;
|
extern SYS_CONFIG SysConfig;
|
||||||
|
|
||||||
|
|
@ -97,7 +96,9 @@ static void funct_mqtt_2_test(char *argres, int rw)
|
||||||
|
|
||||||
static void funct_def_interface(char *argres, int rw)
|
static void funct_def_interface(char *argres, int rw)
|
||||||
{
|
{
|
||||||
GetDefaultNetIFName(argres);
|
char interface[3];
|
||||||
|
GetDefaultNetIFName(interface);
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funct_time(char *argres, int rw)
|
static void funct_time(char *argres, int rw)
|
||||||
|
|
@ -107,6 +108,20 @@ static void funct_time(char *argres, int rw)
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) now);
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void funct_time_set(char *argres, int rw)
|
||||||
|
{
|
||||||
|
time_t unix = atoi(argres);
|
||||||
|
if (unix == 0)
|
||||||
|
{
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "\"ERROR_UNIX_TIME_NULL\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = unix;
|
||||||
|
SetSystemTimeVal(&tv, "Time set from user API");
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "\"TIME_SET_OK\"");
|
||||||
|
}
|
||||||
|
|
||||||
static void funct_uptime(char *argres, int rw)
|
static void funct_uptime(char *argres, int rw)
|
||||||
{
|
{
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) GetUpTime());
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) GetUpTime());
|
||||||
|
|
@ -216,7 +231,6 @@ static void funct_wifiscanres(char *argres, int rw)
|
||||||
strcpy(argres, "\"SYS_ERROR_UNKNOWN\"");
|
strcpy(argres, "\"SYS_ERROR_UNKNOWN\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||||
void funct_gsm_module(char *argres, int rw)
|
void funct_gsm_module(char *argres, int rw)
|
||||||
{
|
{
|
||||||
|
|
@ -255,7 +269,6 @@ void funct_gsm_rssi(char *argres, int rw)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||||
void funct_lora_stat(char *argres, int rw)
|
void funct_lora_stat(char *argres, int rw)
|
||||||
{
|
{
|
||||||
|
|
@ -283,7 +296,6 @@ void funct_lora_appkey(char *argres, int rw)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void funct_ota_state(char *argres, int rw)
|
static void funct_ota_state(char *argres, int rw)
|
||||||
{
|
{
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", GetUpdateStatus());
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", GetUpdateStatus());
|
||||||
|
|
@ -301,50 +313,8 @@ static void funct_ota_newver(char *argres, int rw)
|
||||||
//CRON implementation BEGIN
|
//CRON implementation BEGIN
|
||||||
static void funct_cronrecs(char *argres, int rw)
|
static void funct_cronrecs(char *argres, int rw)
|
||||||
{
|
{
|
||||||
if (rw)
|
CronRecordsInterface(argres, rw);
|
||||||
{
|
|
||||||
struct jReadElement result;
|
|
||||||
cron_timer_t T = { 0 };
|
|
||||||
jRead(argres, "", &result);
|
|
||||||
if (result.dataType == JREAD_ARRAY)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < result.elements; i++)
|
|
||||||
{
|
|
||||||
T.num = jRead_int(argres, "[*{'num'", &i);
|
|
||||||
T.del = jRead_int(argres, "[*{'del'", &i);
|
|
||||||
T.enab = jRead_int(argres, "[*{'enab'", &i);
|
|
||||||
T.prev = jRead_int(argres, "[*{'prev'", &i);
|
|
||||||
jRead_string(argres, "[*{'name'", T.name, sizeof(T.name), &i);
|
|
||||||
jRead_string(argres, "[*{'cron'", T.cron, sizeof(T.cron), &i);
|
|
||||||
jRead_string(argres, "[*{'exec'", T.exec, sizeof(T.exec), &i);
|
|
||||||
memcpy(&GetSysConf()->Timers[T.num - 1], &T, sizeof(cron_timer_t));
|
|
||||||
}
|
|
||||||
ReloadCronSheduler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct jWriteControl jwc;
|
|
||||||
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT);
|
|
||||||
for (int idx = 0; idx < CRON_TIMERS_NUMBER; idx++)
|
|
||||||
{
|
|
||||||
cron_timer_t T;
|
|
||||||
memcpy(&T, &GetSysConf()->Timers[idx], sizeof(cron_timer_t));
|
|
||||||
jwArr_object(&jwc);
|
|
||||||
jwObj_int(&jwc, "num", (unsigned int) T.num);
|
|
||||||
jwObj_int(&jwc, "del", (T.del) ? 1 : 0);
|
|
||||||
jwObj_int(&jwc, "enab", (T.enab) ? 1 : 0);
|
|
||||||
jwObj_int(&jwc, "prev", (T.prev) ? 1 : 0);
|
|
||||||
jwObj_string(&jwc, "name", T.name);
|
|
||||||
jwObj_string(&jwc, "cron", T.cron);
|
|
||||||
jwObj_string(&jwc, "exec", T.exec);
|
|
||||||
jwEnd(&jwc);
|
|
||||||
}
|
|
||||||
jwClose(&jwc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//CRON implementation END
|
//CRON implementation END
|
||||||
|
|
||||||
static void funct_serial_mode(char *argres, int rw)
|
static void funct_serial_mode(char *argres, int rw)
|
||||||
|
|
@ -358,139 +328,73 @@ static void funct_serial_mode(char *argres, int rw)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void funct_objsinfo(char *argres, int rw)
|
static void funct_objsinfo(char *argres, int rw)
|
||||||
{
|
{
|
||||||
GetObjectsInfo(argres);
|
GetObjectsInfo(argres);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *EXEC_ERROR[] = {
|
||||||
|
"EXECUTED_OK",
|
||||||
|
"ERROR_TOO_LONG_COMMAND",
|
||||||
|
"ERROR_OBJECT_NOT_PARSED",
|
||||||
|
"ERROR_ACTION_NOT_PARSED",
|
||||||
|
"ERROR_OBJECT_NOT_FOUND",
|
||||||
|
"ERROR_ACTION_NOT_FOUND",
|
||||||
|
"ERROR_HANDLER_NOT_IMPLEMENTED",
|
||||||
|
};
|
||||||
|
|
||||||
static void funct_exec(char *argres, int rw)
|
static void funct_exec(char *argres, int rw)
|
||||||
{
|
{
|
||||||
if (rw)
|
int res = ExecCommand(argres);
|
||||||
ExecCommand(argres);
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", EXEC_ERROR[res]);
|
||||||
else
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"EXECUTED\"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *dirpath = "/data/";
|
|
||||||
|
|
||||||
static void funct_file_list(char *argres, int rw)
|
static void funct_file_list(char *argres, int rw)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_SDCARD_ENABLE
|
||||||
char entrypath[FILE_PATH_MAX];
|
FileListHandler(argres, rw, "/sdcard/");
|
||||||
char entrysize[16];
|
#else
|
||||||
const char *entrytype = "file";
|
FileListHandler(argres, rw, "/data/");
|
||||||
struct dirent *entry;
|
#endif
|
||||||
struct stat entry_stat;
|
|
||||||
DIR *dir = opendir(dirpath);
|
|
||||||
const size_t dirpath_len = strlen(dirpath);
|
|
||||||
strlcpy(entrypath, dirpath, sizeof(entrypath));
|
|
||||||
|
|
||||||
if (!dir)
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "Failed to stat dir : %s", dirpath);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct jWriteControl jwc;
|
|
||||||
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT);
|
|
||||||
while ((entry = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
|
|
||||||
entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
|
|
||||||
if (stat(entrypath, &entry_stat) == -1)
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "Failed to stat %s : %s", entrytype, entry->d_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
jwArr_object(&jwc);
|
|
||||||
jwObj_string(&jwc, "name", (char*) entry->d_name);
|
|
||||||
jwObj_string(&jwc, "type", entrytype);
|
|
||||||
jwObj_int(&jwc, "size", entry_stat.st_size);
|
|
||||||
jwEnd(&jwc);
|
|
||||||
}
|
|
||||||
jwClose(&jwc);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funct_file_delete(char *argres, int rw)
|
static void funct_file_block(char *argres, int rw)
|
||||||
{
|
{
|
||||||
char filepath[FILE_PATH_MAX];
|
#if CONFIG_SDCARD_ENABLE
|
||||||
struct stat file_stat;
|
FileBlockHandler(argres, rw, "/sdcard/");
|
||||||
const char *filename = argres;
|
#else
|
||||||
if (!filename)
|
FileBlockHandler(argres, rw, "/data/");
|
||||||
{
|
#endif
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename[strlen(filename) - 1] == '/')
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "Invalid filename : %s", filename);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(filepath, dirpath);
|
|
||||||
strcat(filepath, filename);
|
|
||||||
|
|
||||||
ESP_LOGI("FILE_API", " filepath to delete : %s", filepath);
|
|
||||||
|
|
||||||
if (stat(filepath, &file_stat) == -1)
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "File does not exist : %s", filename);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
/* Respond with 400 Bad Request */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unlink(filepath);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funct_file_get(char *argres, int rw)
|
#if CONFIG_SDCARD_ENABLE
|
||||||
|
static void funct_sd_list(char *argres, int rw)
|
||||||
{
|
{
|
||||||
char filepath[FILE_PATH_MAX];
|
FileListHandler(argres, rw, "/sdcard/");
|
||||||
struct stat file_stat;
|
|
||||||
const char *filename = argres;
|
|
||||||
if (!filename)
|
|
||||||
{
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename[strlen(filename) - 1] == '/')
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "Invalid filename : %s", filename);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(filepath, dirpath);
|
|
||||||
strcat(filepath, filename);
|
|
||||||
|
|
||||||
ESP_LOGI("FILE_API", " filepath to delete : %s", filepath);
|
|
||||||
|
|
||||||
if (stat(filepath, &file_stat) == -1)
|
|
||||||
{
|
|
||||||
ESP_LOGE("FILE_API", "File does not exist : %s", filename);
|
|
||||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
|
||||||
/* Respond with 400 Bad Request */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funct_file_put(char *argres, int rw)
|
static void funct_sd_block(char *argres, int rw)
|
||||||
{
|
{
|
||||||
|
FileBlockHandler(argres, rw, "/sdcard/");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void funct_lat(char *argres, int rw)
|
||||||
|
{
|
||||||
|
if (rw)
|
||||||
|
{
|
||||||
|
GetSysConf()->sntpClient.lat = atof(argres);
|
||||||
|
}
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%f", GetSysConf()->sntpClient.lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void funct_raw_data(char *argres, int rw)
|
static void funct_lon(char *argres, int rw)
|
||||||
{
|
{
|
||||||
RawDataHandler(argres, rw);
|
if (rw)
|
||||||
|
{
|
||||||
|
GetSysConf()->sntpClient.lon = atof(argres);
|
||||||
|
}
|
||||||
|
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%f", GetSysConf()->sntpClient.lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int hw_rev = CONFIG_BOARD_HARDWARE_REVISION;
|
const int hw_rev = CONFIG_BOARD_HARDWARE_REVISION;
|
||||||
|
|
@ -500,8 +404,9 @@ const bool VAR_FALSE = false;
|
||||||
const rest_var_t SystemVariables[] =
|
const rest_var_t SystemVariables[] =
|
||||||
{
|
{
|
||||||
|
|
||||||
{ 0, "exec", &funct_exec, VAR_FUNCT, RW, 0, 0 },
|
{ 0, "exec", &funct_exec, VAR_FUNCT, RW, 0, 0 },
|
||||||
{ 0, "time", &funct_time, VAR_FUNCT, R, 0, 0 },
|
{ 0, "time", &funct_time, VAR_FUNCT, R, 0, 0 },
|
||||||
|
{ 0, "time_set", &funct_time_set, VAR_FUNCT, RW, 0, 0 },
|
||||||
{ 0, "uptime", &funct_uptime, VAR_FUNCT, R, 0, 0 },
|
{ 0, "uptime", &funct_uptime, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "free_ram", &funct_fram, VAR_FUNCT, R, 0, 0 },
|
{ 0, "free_ram", &funct_fram, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "free_ram_min", &funct_fram_min, VAR_FUNCT, R, 0, 0 },
|
{ 0, "free_ram_min", &funct_fram_min, VAR_FUNCT, R, 0, 0 },
|
||||||
|
|
@ -514,14 +419,12 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "hw_rev", ((int*) &hw_rev), VAR_INT, R, 1, 1024 },
|
{ 0, "hw_rev", ((int*) &hw_rev), VAR_INT, R, 1, 1024 },
|
||||||
//{ 0, "hw_opt", CONFIG_BOARD_HARDWARE_OPTION, VAR_STRING, R, 1, 256 },
|
//{ 0, "hw_opt", CONFIG_BOARD_HARDWARE_OPTION, VAR_STRING, R, 1, 256 },
|
||||||
|
|
||||||
|
|
||||||
{ 0, "net_bios_name", &SysConfig.NetBIOSName, VAR_STRING, RW, 3, 31 },
|
{ 0, "net_bios_name", &SysConfig.NetBIOSName, VAR_STRING, RW, 3, 31 },
|
||||||
{ 0, "sys_name", &SysConfig.SysName, VAR_STRING, RW, 3, 31 },
|
{ 0, "sys_name", &SysConfig.SysName, VAR_STRING, RW, 3, 31 },
|
||||||
{ 0, "sys_pass", &SysConfig.SysPass, VAR_PASS, RW, 3, 31 },
|
{ 0, "sys_pass", &SysConfig.SysPass, VAR_PASS, RW, 3, 31 },
|
||||||
{ 0, "primary_color", CONFIG_WEBGUIAPP_ACCENT_COLOR, VAR_STRING, RW, 3, 31 },
|
{ 0, "primary_color", CONFIG_WEBGUIAPP_ACCENT_COLOR, VAR_STRING, RW, 3, 31 },
|
||||||
{ 0, "dark_theme", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
{ 0, "dark_theme", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||||
|
|
||||||
|
|
||||||
{ 0, "ota_url", &SysConfig.OTAURL, VAR_STRING, RW, 3, 128 },
|
{ 0, "ota_url", &SysConfig.OTAURL, VAR_STRING, RW, 3, 128 },
|
||||||
{ 0, "ota_auto_int", &SysConfig.OTAAutoInt, VAR_INT, RW, 0, 65535 },
|
{ 0, "ota_auto_int", &SysConfig.OTAAutoInt, VAR_INT, RW, 0, 65535 },
|
||||||
{ 0, "ota_state", &funct_ota_state, VAR_FUNCT, R, 0, 0 },
|
{ 0, "ota_state", &funct_ota_state, VAR_FUNCT, R, 0, 0 },
|
||||||
|
|
@ -544,6 +447,9 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "sntp_serv3", &SysConfig.sntpClient.SntpServer3Adr, VAR_STRING, RW, 3, 32 },
|
{ 0, "sntp_serv3", &SysConfig.sntpClient.SntpServer3Adr, VAR_STRING, RW, 3, 32 },
|
||||||
{ 0, "sntp_enab", &SysConfig.sntpClient.Flags1.bIsGlobalEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "sntp_enab", &SysConfig.sntpClient.Flags1.bIsGlobalEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
|
|
||||||
|
{ 0, "lat", &funct_lat, VAR_FUNCT, RW, 0, 0 },
|
||||||
|
{ 0, "lon", &funct_lon, VAR_FUNCT, RW, 0, 0 },
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
||||||
{ 0, "mqtt_1_enab", &SysConfig.mqttStation[0].Flags1.bIsGlobalEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "mqtt_1_enab", &SysConfig.mqttStation[0].Flags1.bIsGlobalEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
{ 0, "mqtt_1_serv", &SysConfig.mqttStation[0].ServerAddr, VAR_STRING, RW, 3, 63 },
|
{ 0, "mqtt_1_serv", &SysConfig.mqttStation[0].ServerAddr, VAR_STRING, RW, 3, 63 },
|
||||||
|
|
@ -612,7 +518,7 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "wifi_scan_res", &funct_wifiscanres, VAR_FUNCT, R, 0, 0 },
|
{ 0, "wifi_scan_res", &funct_wifiscanres, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "wifi_level", &funct_wifi_level, VAR_FUNCT, R, 0, 0 },
|
{ 0, "wifi_level", &funct_wifi_level, VAR_FUNCT, R, 0, 0 },
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||||
{ 0, "gsm_enab", &SysConfig.gsmSettings.Flags1.bIsGSMEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "gsm_enab", &SysConfig.gsmSettings.Flags1.bIsGSMEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
|
|
@ -630,7 +536,7 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "gsm_dns2", &SysConfig.gsmSettings.DNSAddr2, VAR_IPADDR, RW, 0, 0 },
|
{ 0, "gsm_dns2", &SysConfig.gsmSettings.DNSAddr2, VAR_IPADDR, RW, 0, 0 },
|
||||||
{ 0, "gsm_dns3", &SysConfig.gsmSettings.DNSAddr3, VAR_IPADDR, RW, 0, 0 },
|
{ 0, "gsm_dns3", &SysConfig.gsmSettings.DNSAddr3, VAR_IPADDR, RW, 0, 0 },
|
||||||
{ 0, "gsm_stat", &funct_gsm_stat, VAR_FUNCT, R, 0, 0 },
|
{ 0, "gsm_stat", &funct_gsm_stat, VAR_FUNCT, R, 0, 0 },
|
||||||
#ifdef CONFIG_WEBGUIAPP_MODEM_AT_ACCESS
|
#ifdef CONFIG_WEBGUIAPP_MODEM_AT_ACCESS
|
||||||
{ 0, "gsm_at_timeout", &funct_gsm_at_timeout, VAR_FUNCT, R, 0, 0 },
|
{ 0, "gsm_at_timeout", &funct_gsm_at_timeout, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "gsm_at", &funct_gsm_at, VAR_FUNCT, R, 0, 0 },
|
{ 0, "gsm_at", &funct_gsm_at, VAR_FUNCT, R, 0, 0 },
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -638,7 +544,7 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "gsm_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
{ 0, "gsm_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||||
#else
|
#else
|
||||||
{ 0, "gsm_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
{ 0, "gsm_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
|
||||||
{ 0, "serial_enab", &SysConfig.serialSettings.Flags.IsSerialEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "serial_enab", &SysConfig.serialSettings.Flags.IsSerialEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
|
|
@ -647,14 +553,13 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "serial_baud", &SysConfig.serialSettings.BaudRate, VAR_INT, RW, 1200, 4096000 },
|
{ 0, "serial_baud", &SysConfig.serialSettings.BaudRate, VAR_INT, RW, 1200, 4096000 },
|
||||||
{ 0, "serial_break", &SysConfig.serialSettings.InputBrake, VAR_INT, RW, 1, 50 },
|
{ 0, "serial_break", &SysConfig.serialSettings.InputBrake, VAR_INT, RW, 1, 50 },
|
||||||
{ 0, "serial_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
{ 0, "serial_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||||
#else
|
#else
|
||||||
{ 0, "serial_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
{ 0, "serial_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||||
{ 0, "lora_enab", &SysConfig.lorawanSettings.Flags1.bIsLoRaWANEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "lora_enab", &SysConfig.lorawanSettings.Flags1.bIsLoRaWANEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
{ 0, "lora_visible", (bool*) (&VAR_TRUE), VAR_BOOL, RW, 0, 1 },
|
{ 0, "lora_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||||
{ 0, "lora_devid", &funct_lora_devid, VAR_FUNCT, RW, 0, 0 },
|
{ 0, "lora_devid", &funct_lora_devid, VAR_FUNCT, RW, 0, 0 },
|
||||||
{ 0, "lora_appid", &funct_lora_appid, VAR_FUNCT, RW, 0, 0 },
|
{ 0, "lora_appid", &funct_lora_appid, VAR_FUNCT, RW, 0, 0 },
|
||||||
{ 0, "lora_appkey", &funct_lora_appkey, VAR_FUNCT, R, 0, 0 },
|
{ 0, "lora_appkey", &funct_lora_appkey, VAR_FUNCT, R, 0, 0 },
|
||||||
|
|
@ -662,12 +567,7 @@ const rest_var_t SystemVariables[] =
|
||||||
|
|
||||||
#else
|
#else
|
||||||
{ 0, "lora_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
{ 0, "lora_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_MBTCP_ENABLED
|
#ifdef CONFIG_WEBGUIAPP_MBTCP_ENABLED
|
||||||
{ 0, "mbtcp_enab", &SysConfig.modbusSettings.IsModbusTCPEnabled, VAR_BOOL, RW, 0, 1 },
|
{ 0, "mbtcp_enab", &SysConfig.modbusSettings.IsModbusTCPEnabled, VAR_BOOL, RW, 0, 1 },
|
||||||
|
|
@ -675,20 +575,22 @@ const rest_var_t SystemVariables[] =
|
||||||
{ 0, "mbtcp_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
{ 0, "mbtcp_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||||
#else
|
#else
|
||||||
{ 0, "mbtcp_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
{ 0, "mbtcp_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||||
#endif
|
#endif
|
||||||
{ 0, "cronrecs", &funct_cronrecs, VAR_FUNCT, RW, 0, 0 },
|
{ 0, "cronrecs", &funct_cronrecs, VAR_FUNCT, RW, 0, 0 },
|
||||||
{ 0, "objsinfo", &funct_objsinfo, VAR_FUNCT, R, 0, 0 },
|
{ 0, "objsinfo", &funct_objsinfo, VAR_FUNCT, R, 0, 0 },
|
||||||
|
|
||||||
{ 0, "file_list", &funct_file_list, VAR_FUNCT, R, 0, 0 },
|
{ 0, "file_list", &funct_file_list, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "file_delete", &funct_file_delete, VAR_FUNCT, R, 0, 0 },
|
{ 0, "file_block", &funct_file_block, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "file_get", &funct_file_get, VAR_FUNCT, R, 0, 0 },
|
#if CONFIG_SDCARD_ENABLE
|
||||||
{ 0, "file_put", &funct_file_put, VAR_FUNCT, R, 0, 0 },
|
{ 0, "sd_list", &funct_sd_list, VAR_FUNCT, R, 0, 0 },
|
||||||
|
{ 0, "sd_block", &funct_sd_block, VAR_FUNCT, R, 0, 0 },
|
||||||
{ 0, "raw_data", &funct_raw_data, VAR_FUNCT, R, 0, 0 },
|
{ 0, "sd_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 }
|
||||||
|
#else
|
||||||
|
{ 0, "sd_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
esp_err_t SetConfVar(char *name, char *val, rest_var_types *tp)
|
esp_err_t SetConfVar(char *name, char *val, rest_var_types *tp)
|
||||||
{
|
{
|
||||||
rest_var_t *V = NULL;
|
rest_var_t *V = NULL;
|
||||||
|
|
@ -730,6 +632,12 @@ esp_err_t SetConfVar(char *name, char *val, rest_var_types *tp)
|
||||||
else
|
else
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
break;
|
break;
|
||||||
|
case VAR_CHAR:
|
||||||
|
constr = atoi(val);
|
||||||
|
if (constr < V->minlen || constr > V->maxlen)
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
*((uint8_t*) V->ref) = constr;
|
||||||
|
break;
|
||||||
case VAR_INT:
|
case VAR_INT:
|
||||||
constr = atoi(val);
|
constr = atoi(val);
|
||||||
if (constr < V->minlen || constr > V->maxlen)
|
if (constr < V->minlen || constr > V->maxlen)
|
||||||
|
|
@ -799,6 +707,9 @@ esp_err_t GetConfVar(char *name, char *val, rest_var_types *tp)
|
||||||
case VAR_INT:
|
case VAR_INT:
|
||||||
itoa(*((int*) V->ref), val, 10);
|
itoa(*((int*) V->ref), val, 10);
|
||||||
break;
|
break;
|
||||||
|
case VAR_CHAR:
|
||||||
|
itoa(*((uint8_t*) V->ref), val, 10);
|
||||||
|
break;
|
||||||
case VAR_STRING:
|
case VAR_STRING:
|
||||||
strcpy(val, (char*) V->ref);
|
strcpy(val, (char*) V->ref);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
18
src/SNTP.c
18
src/SNTP.c
|
|
@ -134,9 +134,27 @@ void StartSystemTimer(void)
|
||||||
ESP_ERROR_CHECK(esp_timer_start_periodic(system_seconds_timer, 1000000));
|
ESP_ERROR_CHECK(esp_timer_start_periodic(system_seconds_timer, 1000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetSystemTime(struct tm *time, const char* source)
|
||||||
|
{
|
||||||
|
time_t t = mktime(time);
|
||||||
|
ESP_LOGI("SNTP","Setting time: %s from the source %s", asctime(time), source);
|
||||||
|
struct timeval now = { .tv_sec = t };
|
||||||
|
settimeofday(&now, NULL);
|
||||||
|
TimeObtainHandler(&now);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSystemTimeVal(struct timeval *tv, const char* source)
|
||||||
|
{
|
||||||
|
ESP_LOGI("SNTP","Setting time: %d from the source %s", (int)(tv->tv_sec), source);
|
||||||
|
settimeofday(tv, NULL);
|
||||||
|
TimeObtainHandler(tv);
|
||||||
|
}
|
||||||
|
|
||||||
void SecondTickSystem(void *param)
|
void SecondTickSystem(void *param)
|
||||||
{
|
{
|
||||||
++UpTime;
|
++UpTime;
|
||||||
|
MidnightTimer();
|
||||||
|
FileBlockTimeoutCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetUpTime(void)
|
uint32_t GetUpTime(void)
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ void serial_RX_task(void *arg)
|
||||||
|
|
||||||
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
||||||
{
|
{
|
||||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 0);
|
ExternalServiceMQTTSend(EXTERNAL_SERVICE_NAME, rxbuf, buffered_size, 0);
|
||||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 1);
|
ExternalServiceMQTTSend(EXTERNAL_SERVICE_NAME, rxbuf, buffered_size, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReceiveHandlerAPI();
|
ReceiveHandlerAPI();
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
|
||||||
jwObj_int(&jwc, "msgid", MSG->parsedData.msgID);
|
jwObj_int(&jwc, "msgid", MSG->parsedData.msgID);
|
||||||
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
|
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
|
||||||
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
||||||
char time[RFC3339_TIMESTAMP_LENGTH];
|
char time[ISO8601_TIMESTAMP_LENGTH];
|
||||||
GetRFC3339Time(time);
|
GetISO8601Time(time);
|
||||||
jwObj_string(&jwc, "time", time);
|
jwObj_string(&jwc, "time", time);
|
||||||
jwObj_int(&jwc, "msgtype", DATA_MESSAGE_TYPE_RESPONSE);
|
jwObj_int(&jwc, "msgtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||||
jwObj_int(&jwc, "payloadtype", MSG->parsedData.payloadType);
|
jwObj_int(&jwc, "payloadtype", MSG->parsedData.payloadType);
|
||||||
|
|
@ -330,8 +330,8 @@ esp_err_t ServiceDataHandler(data_message_t *MSG)
|
||||||
jwObj_int(&jwc, "msgid", MSG->parsedData.msgID);
|
jwObj_int(&jwc, "msgid", MSG->parsedData.msgID);
|
||||||
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
|
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
|
||||||
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
||||||
char time[RFC3339_TIMESTAMP_LENGTH];
|
char time[ISO8601_TIMESTAMP_LENGTH];
|
||||||
GetRFC3339Time(time);
|
GetISO8601Time(time);
|
||||||
jwObj_string(&jwc, "time", time);
|
jwObj_string(&jwc, "time", time);
|
||||||
jwObj_int(&jwc, "messtype", DATA_MESSAGE_TYPE_RESPONSE);
|
jwObj_int(&jwc, "messtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||||
const char *err_br;
|
const char *err_br;
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@ esp_err_t WebGuiAppInit(void)
|
||||||
#if CONFIG_WEBGUIAPP_I2C_ENABLE
|
#if CONFIG_WEBGUIAPP_I2C_ENABLE
|
||||||
InitSysI2C();
|
InitSysI2C();
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_SDCARD_ENABLE
|
||||||
|
InitSysSDCard();
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_err_t err = nvs_flash_init();
|
esp_err_t err = nvs_flash_init();
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
|
@ -106,7 +109,7 @@ esp_err_t WebGuiAppInit(void)
|
||||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND
|
||||||
||
|
||
|
||||||
MANUAL_RESET == 1
|
MANUAL_RESET == 1
|
||||||
#if (MAIN_FUNCTIONAL_BUTTON_GPIO >= 0)
|
#if (MAIN_FUNCTIONAL_BUTTON_GPIO >= 0)
|
||||||
|| gpio_get_level(MAIN_FUNCTIONAL_BUTTON_GPIO) == 0
|
|| gpio_get_level(MAIN_FUNCTIONAL_BUTTON_GPIO) == 0
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
|
|
@ -157,7 +160,8 @@ esp_err_t WebGuiAppInit(void)
|
||||||
/*Start services depends on client connection*/
|
/*Start services depends on client connection*/
|
||||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE || CONFIG_WEBGUIAPP_ETHERNET_ENABLE || CONFIG_WEBGUIAPP_WIFI_ENABLE
|
#if CONFIG_WEBGUIAPP_GPRS_ENABLE || CONFIG_WEBGUIAPP_ETHERNET_ENABLE || CONFIG_WEBGUIAPP_WIFI_ENABLE
|
||||||
ESP_ERROR_CHECK(start_file_server());
|
ESP_ERROR_CHECK(start_file_server());
|
||||||
StartTimeGet();
|
if (GetSysConf()->sntpClient.Flags1.bIsGlobalEnabled)
|
||||||
|
StartTimeGet();
|
||||||
//regTimeSyncCallback(&TimeObtainHandler);
|
//regTimeSyncCallback(&TimeObtainHandler);
|
||||||
//mDNSServiceStart();
|
//mDNSServiceStart();
|
||||||
|
|
||||||
|
|
@ -174,7 +178,6 @@ esp_err_t WebGuiAppInit(void)
|
||||||
InitSerialPort();
|
InitSerialPort();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,7 +252,7 @@ static void ResetSysConfig(SYS_CONFIG *Conf)
|
||||||
|
|
||||||
UINT32_VAL d;
|
UINT32_VAL d;
|
||||||
GetChipId((uint8_t*) d.v);
|
GetChipId((uint8_t*) d.v);
|
||||||
snprintf(Conf->SN, 11, "%010u", (unsigned int)swap(d.Val));
|
snprintf(Conf->SN, 11, "%010u", (unsigned int) swap(d.Val));
|
||||||
|
|
||||||
Conf->ColorSheme = CONFIG_WEBGUIAPP_DEFAULT_COLOR_SCHEME;
|
Conf->ColorSheme = CONFIG_WEBGUIAPP_DEFAULT_COLOR_SCHEME;
|
||||||
|
|
||||||
|
|
@ -361,23 +364,29 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME));
|
sizeof(CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME));
|
||||||
memcpy(Conf->mqttStation[0].GroupName, CONFIG_WEBGUIAPP_MQTT_GROUP_NAME,
|
memcpy(Conf->mqttStation[0].GroupName, CONFIG_WEBGUIAPP_MQTT_GROUP_NAME,
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_GROUP_NAME));
|
sizeof(CONFIG_WEBGUIAPP_MQTT_GROUP_NAME));
|
||||||
memcpy(Conf->mqttStation[0].ClientID, CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_1,
|
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_1));
|
Conf->mqttStation[0].ClientID[0] = 0x00;
|
||||||
|
strcat(Conf->mqttStation[0].ClientID, CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_1);
|
||||||
|
strcat(Conf->mqttStation[0].ClientID, "-");
|
||||||
|
strcat(Conf->mqttStation[0].ClientID, Conf->ID);
|
||||||
|
|
||||||
memcpy(Conf->mqttStation[0].UserName, CONFIG_WEBGUIAPP_MQTT_USERNAME,
|
memcpy(Conf->mqttStation[0].UserName, CONFIG_WEBGUIAPP_MQTT_USERNAME,
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_USERNAME));
|
sizeof(CONFIG_WEBGUIAPP_MQTT_USERNAME));
|
||||||
memcpy(Conf->mqttStation[0].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD,
|
memcpy(Conf->mqttStation[0].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD,
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
||||||
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
|
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
|
||||||
Conf->mqttStation[1].Flags1.bIsGlobalEnabled = false;
|
Conf->mqttStation[1].Flags1.bIsGlobalEnabled = false;
|
||||||
#if CONFIG_WEBGUIAPP_MQTT_ON
|
|
||||||
Conf->mqttStation[1].Flags1.bIsGlobalEnabled = true;
|
|
||||||
#endif
|
|
||||||
memcpy(Conf->mqttStation[1].ServerAddr, CONFIG_WEBGUIAPP_MQTT_SERVER_URL, sizeof(CONFIG_WEBGUIAPP_MQTT_SERVER_URL));
|
memcpy(Conf->mqttStation[1].ServerAddr, CONFIG_WEBGUIAPP_MQTT_SERVER_URL, sizeof(CONFIG_WEBGUIAPP_MQTT_SERVER_URL));
|
||||||
Conf->mqttStation[1].ServerPort = CONFIG_WEBGUIAPP_MQTT_SERVER_PORT;
|
Conf->mqttStation[1].ServerPort = CONFIG_WEBGUIAPP_MQTT_SERVER_PORT;
|
||||||
memcpy(Conf->mqttStation[1].SystemName, CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME,
|
memcpy(Conf->mqttStation[1].SystemName, CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME,
|
||||||
sizeof(CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME));
|
sizeof(CONFIG_WEBGUIAPP_MQTT_SYSTEM_NAME));
|
||||||
memcpy(Conf->mqttStation[1].GroupName, CONFIG_WEBGUIAPP_MQTT_GROUP_NAME, sizeof(CONFIG_WEBGUIAPP_MQTT_GROUP_NAME));
|
memcpy(Conf->mqttStation[1].GroupName, CONFIG_WEBGUIAPP_MQTT_GROUP_NAME, sizeof(CONFIG_WEBGUIAPP_MQTT_GROUP_NAME));
|
||||||
memcpy(Conf->mqttStation[1].ClientID, CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_2, sizeof(CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_2));
|
|
||||||
|
Conf->mqttStation[1].ClientID[0] = 0x00;
|
||||||
|
strcat(Conf->mqttStation[1].ClientID, CONFIG_WEBGUIAPP_MQTT_CLIENT_ID_2);
|
||||||
|
strcat(Conf->mqttStation[1].ClientID, "-");
|
||||||
|
strcat(Conf->mqttStation[1].ClientID, Conf->ID);
|
||||||
|
|
||||||
memcpy(Conf->mqttStation[1].UserName, CONFIG_WEBGUIAPP_MQTT_USERNAME, sizeof(CONFIG_WEBGUIAPP_MQTT_USERNAME));
|
memcpy(Conf->mqttStation[1].UserName, CONFIG_WEBGUIAPP_MQTT_USERNAME, sizeof(CONFIG_WEBGUIAPP_MQTT_USERNAME));
|
||||||
memcpy(Conf->mqttStation[1].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD, sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
memcpy(Conf->mqttStation[1].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD, sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -390,6 +399,8 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
|
||||||
sizeof(CONFIG_WEBGUIAPP_SNTP_HOST_3));
|
sizeof(CONFIG_WEBGUIAPP_SNTP_HOST_3));
|
||||||
Conf->sntpClient.Flags1.bIsGlobalEnabled = CONFIG_WEBGUIAPP_SNTP_AUTOUPDATE_ENABLE;
|
Conf->sntpClient.Flags1.bIsGlobalEnabled = CONFIG_WEBGUIAPP_SNTP_AUTOUPDATE_ENABLE;
|
||||||
Conf->sntpClient.TimeZone = CONFIG_WEBGUIAPP_SNTP_TIMEZONE;
|
Conf->sntpClient.TimeZone = CONFIG_WEBGUIAPP_SNTP_TIMEZONE;
|
||||||
|
Conf->sntpClient.lat = 0.0;
|
||||||
|
Conf->sntpClient.lon = 0.0;
|
||||||
|
|
||||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||||
Conf->lorawanSettings.Flags1.bIsLoRaWANEnabled = true;
|
Conf->lorawanSettings.Flags1.bIsLoRaWANEnabled = true;
|
||||||
|
|
@ -424,17 +435,23 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
|
||||||
#endif
|
#endif
|
||||||
Conf->modbusSettings.ModbusTCPPort = CONFIG_WEBGUIAPP_MBTCP_SERVER_PORT;
|
Conf->modbusSettings.ModbusTCPPort = CONFIG_WEBGUIAPP_MBTCP_SERVER_PORT;
|
||||||
#endif
|
#endif
|
||||||
for (int i = 0; i < CONFIG_WEBGUIAPP_CRON_NUMBER; i++ )
|
for (int i = 0; i < CONFIG_WEBGUIAPP_CRON_NUMBER; i++)
|
||||||
{
|
{
|
||||||
Conf->Timers[i].num = i+1;
|
Conf->Timers[i].num = i + 1;
|
||||||
Conf->Timers[i].del = true;
|
Conf->Timers[i].del = true;
|
||||||
Conf->Timers[i].enab = false;
|
Conf->Timers[i].enab = false;
|
||||||
Conf->Timers[i].prev = false;
|
Conf->Timers[i].prev = false;
|
||||||
|
Conf->Timers[i].type = 0;
|
||||||
|
Conf->Timers[i].sun_angle = 0;
|
||||||
strcpy(Conf->Timers[i].name, "Timer Name");
|
strcpy(Conf->Timers[i].name, "Timer Name");
|
||||||
strcpy(Conf->Timers[i].cron, "* * * * * *");
|
strcpy(Conf->Timers[i].cron, "* * * * * *");
|
||||||
strcpy(Conf->Timers[i].exec, "OBJECT,ACTION,ARGUMENTS");
|
strcpy(Conf->Timers[i].exec, "OBJECT,ACTION,ARGUMENTS");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_WEBGUIAPP_ASTRO_ENABLE
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t ReadNVSSysConfig(SYS_CONFIG *SysConf)
|
esp_err_t ReadNVSSysConfig(SYS_CONFIG *SysConf)
|
||||||
|
|
@ -562,7 +579,7 @@ void DelayedRestartTask(void *pvParameter)
|
||||||
void DelayedRestart(void)
|
void DelayedRestart(void)
|
||||||
{
|
{
|
||||||
xTaskCreate(DelayedRestartTask, "RestartTask", 1024 * 4, (void*) 0, 3,
|
xTaskCreate(DelayedRestartTask, "RestartTask", 1024 * 4, (void*) 0, 3,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetUserAppNeedReset(void)
|
bool GetUserAppNeedReset(void)
|
||||||
|
|
@ -575,6 +592,70 @@ void SetUserAppNeedReset(bool res)
|
||||||
isUserAppNeedReset = res;
|
isUserAppNeedReset = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LOG_MAX_CHUNK_SIZE CONFIG_WEBGUIAPP_SYSLOG_CHUNK_SIZE
|
||||||
|
#define LOG_MAX_CHUNKS CONFIG_WEBGUIAPP_SYSLOG_MAX_CHUNKS
|
||||||
|
#define DEFAULT_LOG_FILE_NAME "syslog"
|
||||||
|
#define LOG_PARTITION "/data/"
|
||||||
|
|
||||||
|
static void ComposeLogFilename(int chunk, char *filename)
|
||||||
|
{
|
||||||
|
char chunkstr[2];
|
||||||
|
strcpy(filename, LOG_PARTITION);
|
||||||
|
strcat(filename, DEFAULT_LOG_FILE_NAME);
|
||||||
|
itoa(chunk, chunkstr, 10);
|
||||||
|
strcat(filename, chunkstr);
|
||||||
|
strcat(filename, ".log");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysLog(char *format, ...)
|
||||||
|
{
|
||||||
|
char tstamp[ISO8601_TIMESTAMP_LENGTH + 2];
|
||||||
|
static int cur_chunk = 0, isstart = 1;
|
||||||
|
char filename[32];
|
||||||
|
struct stat file_stat;
|
||||||
|
FILE *f;
|
||||||
|
ComposeLogFilename(cur_chunk, filename);
|
||||||
|
|
||||||
|
//If first call after reboot, try to find not full chunk
|
||||||
|
if (isstart)
|
||||||
|
{
|
||||||
|
while (file_stat.st_size > LOG_MAX_CHUNK_SIZE * 1024 && cur_chunk <= LOG_MAX_CHUNKS - 1)
|
||||||
|
{
|
||||||
|
cur_chunk++;
|
||||||
|
ComposeLogFilename(cur_chunk, filename);
|
||||||
|
}
|
||||||
|
isstart = 0;
|
||||||
|
}
|
||||||
|
stat(filename, &file_stat);
|
||||||
|
//next if full, else append to current
|
||||||
|
if (file_stat.st_size > LOG_MAX_CHUNK_SIZE * 1024)
|
||||||
|
{
|
||||||
|
if (++cur_chunk > LOG_MAX_CHUNKS - 1)
|
||||||
|
cur_chunk = 0;
|
||||||
|
ComposeLogFilename(cur_chunk, filename);
|
||||||
|
f = fopen(filename, "w");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f = fopen(filename, "a");
|
||||||
|
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to open file %s for writing", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
va_end(arg);
|
||||||
|
strcpy(tstamp, "\r\n");
|
||||||
|
char ts[ISO8601_TIMESTAMP_LENGTH];
|
||||||
|
GetISO8601Time(ts);
|
||||||
|
strcat(tstamp, ts);
|
||||||
|
strcat(tstamp, " ");
|
||||||
|
fwrite(tstamp, 1, strlen(tstamp), f);
|
||||||
|
vfprintf(f, format, arg);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
void LogFile(char *fname, char *format, ...)
|
void LogFile(char *fname, char *format, ...)
|
||||||
{
|
{
|
||||||
char filename[32];
|
char filename[32];
|
||||||
|
|
|
||||||
119
src/sdcard.c
Normal file
119
src/sdcard.c
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* Copyright 2024 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 name: sdcard.c
|
||||||
|
* Project: webguiapp
|
||||||
|
* Created on: 2024-05-07
|
||||||
|
* Author: bogd
|
||||||
|
* Description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "sdmmc_cmd.h"
|
||||||
|
#include "SysConfiguration.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_SDCARD_ENABLE
|
||||||
|
static const char *TAG = "sdcard";
|
||||||
|
#define MOUNT_POINT "/sdcard"
|
||||||
|
|
||||||
|
// Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu.
|
||||||
|
// You can also change the pin assignments here by changing the following 4 lines.
|
||||||
|
#define PIN_NUM_MISO CONFIG_SDCARD_SPI_MISO_GPIO
|
||||||
|
#define PIN_NUM_MOSI CONFIG_SDCARD_SPI_MOSI_GPIO
|
||||||
|
#define PIN_NUM_CLK CONFIG_SDCARD_SPI_SCLK_GPIO
|
||||||
|
#define PIN_NUM_CS CONFIG_SDCARD_SPI_CS_GPIO
|
||||||
|
|
||||||
|
void InitSysSDCard()
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
// Options for mounting the filesystem.
|
||||||
|
// If format_if_mount_failed is set to true, SD card will be partitioned and
|
||||||
|
// formatted in case when mounting fails.
|
||||||
|
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||||
|
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
|
||||||
|
.format_if_mount_failed = true,
|
||||||
|
#else
|
||||||
|
.format_if_mount_failed = false,
|
||||||
|
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
|
||||||
|
.max_files = 5,
|
||||||
|
.allocation_unit_size = 16 * 1024
|
||||||
|
};
|
||||||
|
sdmmc_card_t *card;
|
||||||
|
const char mount_point[] = MOUNT_POINT;
|
||||||
|
ESP_LOGI(TAG, "Initializing SD card");
|
||||||
|
|
||||||
|
// Use settings defined above to initialize SD card and mount FAT filesystem.
|
||||||
|
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
|
||||||
|
// Please check its source code and implement error recovery when developing
|
||||||
|
// production applications.
|
||||||
|
ESP_LOGI(TAG, "Using SPI peripheral");
|
||||||
|
|
||||||
|
// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
|
||||||
|
// For setting a specific frequency, use host.max_freq_khz (range 400kHz - 20MHz for SDSPI)
|
||||||
|
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
|
||||||
|
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
||||||
|
host.slot = CONFIG_SDCARD_SPI_HOST;
|
||||||
|
|
||||||
|
spi_bus_config_t bus_cfg = {
|
||||||
|
.mosi_io_num = PIN_NUM_MOSI,
|
||||||
|
.miso_io_num = PIN_NUM_MISO,
|
||||||
|
.sclk_io_num = PIN_NUM_CLK,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.max_transfer_sz = 4000,
|
||||||
|
};
|
||||||
|
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize bus.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||||
|
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
||||||
|
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
|
||||||
|
slot_config.gpio_cs = PIN_NUM_CS;
|
||||||
|
slot_config.host_id = host.slot;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Mounting filesystem");
|
||||||
|
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
||||||
|
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
if (ret == ESP_FAIL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(
|
||||||
|
TAG,
|
||||||
|
"Failed to mount filesystem. "
|
||||||
|
"If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
||||||
|
"Make sure SD card lines have pull-up resistors in place.",
|
||||||
|
esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Filesystem mounted");
|
||||||
|
|
||||||
|
// Card has been initialized, print its properties
|
||||||
|
sdmmc_card_print_info(stdout, card);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -35,8 +35,8 @@ function upload() {
|
||||||
|
|
||||||
/* Max size of an individual file. Make sure this
|
/* Max size of an individual file. Make sure this
|
||||||
* value is same as that set in file_server.c */
|
* value is same as that set in file_server.c */
|
||||||
var MAX_FILE_SIZE = 1000*1024;
|
var MAX_FILE_SIZE = 100*1000*1024;
|
||||||
var MAX_FILE_SIZE_STR = "1MB";
|
var MAX_FILE_SIZE_STR = "100MB";
|
||||||
|
|
||||||
if (fileInput.length == 0) {
|
if (fileInput.length == 0) {
|
||||||
alert("No file selected!");
|
alert("No file selected!");
|
||||||
|
|
@ -46,8 +46,8 @@ function upload() {
|
||||||
alert("File path on server cannot have spaces!");
|
alert("File path on server cannot have spaces!");
|
||||||
} else if (filePath[filePath.length-1] == '/') {
|
} else if (filePath[filePath.length-1] == '/') {
|
||||||
alert("File name not specified after path!");
|
alert("File name not specified after path!");
|
||||||
} else if (fileInput[0].size > 1000*1024) {
|
} else if (fileInput[0].size > MAX_FILE_SIZE) {
|
||||||
alert("File size must be less than 1MB!");
|
alert("File size must be less than 100MB!");
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("newfile").disabled = true;
|
document.getElementById("newfile").disabled = true;
|
||||||
document.getElementById("filepath").disabled = true;
|
document.getElementById("filepath").disabled = true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user