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/FileServer.c"
|
||||
"src/HTTPAPISystem.c"
|
||||
# "src/HTTPPrintSystem.c"
|
||||
# "src/HTTPPostSystem.c"
|
||||
"src/CommandProcSys.c"
|
||||
"src/Helpers.c"
|
||||
"src/NetTransport.c"
|
||||
|
|
@ -27,11 +25,13 @@ idf_component_register(
|
|||
"src/MQTT.c"
|
||||
"src/CronTimers.c"
|
||||
"src/SerialPort.c"
|
||||
src/RawMemAPI.c
|
||||
src/sdcard.c
|
||||
src/FileBlockHandler.c
|
||||
src/OTA.c
|
||||
src/RestApiHandler.c
|
||||
src/SysComm.c
|
||||
src/SysErr.c
|
||||
src/EEPROM.c
|
||||
${lora_SRCS}
|
||||
${gprs_SRCS}
|
||||
${jreadwrite_SRCS}
|
||||
|
|
@ -47,6 +47,7 @@ idf_component_register(
|
|||
|
||||
REQUIRES nvs_flash
|
||||
spiffs
|
||||
fatfs
|
||||
esp_http_server
|
||||
mbedtls
|
||||
lwip
|
||||
|
|
|
|||
65
Kconfig
65
Kconfig
|
|
@ -261,6 +261,57 @@ menu "WebGUIApp"
|
|||
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"
|
||||
config WEBGUIAPP_WIFI_ENABLE
|
||||
|
|
@ -865,8 +916,6 @@ menu "WebGUIApp"
|
|||
endif
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
menu "MQTT settings"
|
||||
config WEBGUIAPP_MQTT_ENABLE
|
||||
bool "Enabled MQTT transport"
|
||||
|
|
@ -930,6 +979,18 @@ menu "WebGUIApp"
|
|||
endif
|
||||
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
|
||||
menu "DNS settings"
|
||||
|
||||
|
|
|
|||
|
|
@ -50,13 +50,14 @@ typedef struct
|
|||
bool del; /*!< Flag of non valid record, free for future overwrite */
|
||||
bool enab; /*!< Enable scheduler */
|
||||
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 cron[TIMER_CRONSTRING_LENGTH]; /*!< Cron expression */
|
||||
char exec[TIMER_EXECSTRING_LENGTH]; /*!< Cron command string */
|
||||
|
||||
} cron_timer_t;
|
||||
|
||||
esp_err_t InitCronSheduler();
|
||||
esp_err_t ReloadCronSheduler();
|
||||
char* GetCronError();
|
||||
void DebugTimer();
|
||||
|
|
@ -67,12 +68,15 @@ char* GetCronActionName(int idx);
|
|||
char* GetCronActAvail(int idx);
|
||||
|
||||
void TimeObtainHandler(struct timeval *tm);
|
||||
|
||||
void CronRecordsInterface(char *argres, int rw);
|
||||
void AstroRecordsInterface(char *argres, int rw);
|
||||
/**
|
||||
* \brief Handle all actions under all objects
|
||||
* \param obj Index of the object
|
||||
* \param act Index of the action
|
||||
*/
|
||||
void custom_cron_execute(int obj, int act);
|
||||
void SetSunTimes(uint32_t t);
|
||||
void MidnightTimer();
|
||||
|
||||
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_CRONTIMERS_H_ */
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@
|
|||
|
||||
/* Max length a file path can have on storage */
|
||||
#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_STR "1MB"
|
||||
#define MAX_FILE_SIZE (100*1000*1024) // 200 KB
|
||||
#define MAX_FILE_SIZE_STR "100MB"
|
||||
|
||||
/* Scratch buffer size */
|
||||
#define SCRATCH_BUFSIZE EXPECTED_MAX_DATA_SIZE
|
||||
|
|
@ -84,6 +84,23 @@ typedef struct
|
|||
void (*HandlerRoutine)(char *VarData, void *arg);
|
||||
} 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);
|
||||
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData);
|
||||
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 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_ */
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ typedef int mqtt_app_err_t;
|
|||
#define API_FILE_EMPTY_ERR 15
|
||||
#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
|
||||
{
|
||||
char topic[CONFIG_WEBGUIAPP_MQTT_MAX_TOPIC_LENGTH];
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ void GotEthIF(void);
|
|||
void GetRFC3339Time(char *t);
|
||||
void GetISO8601Time(char *t);
|
||||
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);
|
||||
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_PASS,
|
||||
VAR_IPADDR,
|
||||
VAR_FUNCT
|
||||
VAR_FUNCT,
|
||||
VAR_CHAR
|
||||
} rest_var_types;
|
||||
|
||||
|
||||
|
|
@ -103,6 +104,9 @@ typedef struct
|
|||
{
|
||||
bool bIsGlobalEnabled;
|
||||
} Flags1;
|
||||
float lat;
|
||||
float lon;
|
||||
|
||||
} sntpClient;
|
||||
|
||||
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ typedef struct
|
|||
}UART_DATA_SEND_STRUCT;
|
||||
|
||||
void InitSerialPort(void);
|
||||
void InitSysSDCard();
|
||||
esp_err_t TransmitSerialPort(char *data, int ln);
|
||||
|
||||
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);
|
||||
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_ */
|
||||
|
|
|
|||
|
|
@ -42,5 +42,6 @@ void SetAppVars( rest_var_t* appvars, int size);
|
|||
bool GetUserAppNeedReset(void);
|
||||
void SetUserAppNeedReset(bool res);
|
||||
void LogFile(char *fname, char *format, ...);
|
||||
void SysLog(char *format, ...);
|
||||
|
||||
#endif /* COMPONENTS_WEBGUIAPPCOMPONENT_INCLUDE_WEBGUIAPP_H_ */
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ static int ExecCommandParse(char *cmd)
|
|||
//int err = 0;
|
||||
int commlen = strlen(cmd);
|
||||
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];
|
||||
|
||||
strcpy(comm, cmd);
|
||||
|
|
@ -155,9 +155,9 @@ static int ExecCommandParse(char *cmd)
|
|||
com = strtok(NULL, ",");
|
||||
arg = strtok(NULL, "\0");
|
||||
if (!obj)
|
||||
return 2;
|
||||
return 2; //ERROR_OBJECT_NOT_PARSED
|
||||
if (!com)
|
||||
return 3;
|
||||
return 3; //ERROR_ACTION_NOT_PARSED
|
||||
|
||||
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)
|
||||
{
|
||||
com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
||||
return 0;
|
||||
return 0; //EXECUTED_OK
|
||||
}
|
||||
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)
|
||||
{
|
||||
custom_com_obj_arr[idx].command_handlers[i](obj, com, arg);
|
||||
return 0;
|
||||
return 0; //EXECUTED_OK
|
||||
}
|
||||
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 "webguiapp.h"
|
||||
#include "string.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#define TAG "CRON_TIMER"
|
||||
|
||||
static cron_job *JobsList[CONFIG_WEBGUIAPP_CRON_NUMBER];
|
||||
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()
|
||||
{
|
||||
return cron_express_error;
|
||||
|
|
@ -39,12 +45,6 @@ void custom_cron_job_callback(cron_job *job)
|
|||
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 *err = NULL;
|
||||
|
|
@ -105,6 +105,7 @@ static void ExecuteLastAction(obj_struct_t *objarr)
|
|||
void TimeObtainHandler(struct timeval *tm)
|
||||
{
|
||||
ESP_LOGI(TAG, "Current time updated with value %d", (unsigned int )tm->tv_sec);
|
||||
RecalcAstro(tm->tv_sec);
|
||||
ReloadCronSheduler();
|
||||
ExecuteLastAction(GetSystemObjects());
|
||||
ExecuteLastAction(GetCustomObjects());
|
||||
|
|
@ -150,3 +151,239 @@ esp_err_t ReloadCronSheduler()
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
@ -22,16 +22,16 @@
|
|||
#include <string.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/event_groups.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
|
||||
static EventGroupHandle_t event_group = NULL;
|
||||
|
|
@ -41,46 +41,40 @@ static int ResetType = 0;
|
|||
static bool isPPPinitializing = false;
|
||||
#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 int attimeout = 1000;
|
||||
TaskHandle_t initTaskhandle;
|
||||
|
||||
#define PPP_MODEM_TIMEOUT 40
|
||||
|
||||
MODEM_INFO mod_info = {"-", "-", "-", "-"};
|
||||
esp_netif_t *ppp_netif;
|
||||
esp_modem_dce_t *dce;
|
||||
TaskHandle_t trasporttask;
|
||||
|
||||
static void (*gsm_reset)(uint8_t level) = NULL;
|
||||
void RegGSMReset(void (*gsm_rst)(uint8_t level))
|
||||
{
|
||||
gsm_reset = gsm_rst;
|
||||
}
|
||||
void RegGSMReset(void (*gsm_rst)(uint8_t level)) { gsm_reset = gsm_rst; }
|
||||
|
||||
esp_netif_t* GetPPPNetifAdapter(void)
|
||||
{
|
||||
esp_netif_t *GetPPPNetifAdapter(void) {
|
||||
if (isPPPConn)
|
||||
return ppp_netif;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MODEM_INFO* GetPPPModemInfo(void)
|
||||
{
|
||||
return &mod_info;
|
||||
}
|
||||
MODEM_INFO *GetPPPModemInfo(void) { return &mod_info; }
|
||||
|
||||
bool isPPPConnected(void)
|
||||
{
|
||||
return isPPPConn;
|
||||
}
|
||||
bool isPPPConnected(void) { return isPPPConn; }
|
||||
|
||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id,
|
||||
void *event_data)
|
||||
{
|
||||
int32_t event_id, void *event_data) {
|
||||
ESP_LOGI(TAG, "PPP state changed event %u", (unsigned int)event_id);
|
||||
if (event_id == NETIF_PPP_ERRORUSER)
|
||||
{
|
||||
if (event_id == NETIF_PPP_ERRORUSER) {
|
||||
/* User interrupted event from esp-netif */
|
||||
esp_netif_t *netif = event_data;
|
||||
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
|
||||
|
|
@ -88,21 +82,21 @@ static void on_ppp_changed(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,
|
||||
void *event_data)
|
||||
{
|
||||
int32_t event_id, void *event_data) {
|
||||
ESP_LOGD(TAG, "IP event! %u", (unsigned int)event_id);
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP)
|
||||
{
|
||||
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;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
|
||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||
memcpy(&GetSysConf()->gsmSettings.IPAddr, &event->ip_info.ip, sizeof(event->ip_info.ip));
|
||||
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));
|
||||
memcpy(&GetSysConf()->gsmSettings.IPAddr, &event->ip_info.ip,
|
||||
sizeof(event->ip_info.ip));
|
||||
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
|
||||
|
||||
ESP_LOGI(TAG, "Modem Connect to PPP Server");
|
||||
|
|
@ -118,67 +112,57 @@ static void on_ip_event(void *arg, esp_event_base_t event_base,
|
|||
xEventGroupSetBits(event_group, CONNECT_BIT);
|
||||
isPPPConn = true;
|
||||
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;
|
||||
}
|
||||
else if (event_id == IP_EVENT_GOT_IP6)
|
||||
{
|
||||
} else if (event_id == IP_EVENT_GOT_IP6) {
|
||||
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)
|
||||
{
|
||||
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);
|
||||
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID,
|
||||
&on_ppp_changed);
|
||||
|
||||
if (dce)
|
||||
{
|
||||
if (dce) {
|
||||
esp_modem_destroy(dce);
|
||||
}
|
||||
|
||||
if (ppp_netif != NULL)
|
||||
{
|
||||
if (ppp_netif != NULL) {
|
||||
esp_netif_destroy(ppp_netif);
|
||||
}
|
||||
|
||||
if (starttype == 0)
|
||||
{
|
||||
if (starttype == 0) {
|
||||
ESP_LOGE(TAG, "GSM module power down and up reset");
|
||||
#if 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);
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
#else
|
||||
if (gsm_reset)
|
||||
{
|
||||
if (gsm_reset) {
|
||||
gsm_reset(0);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
gsm_reset(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "ethernet chip reset pin not defined");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "GSM module reset procedure not defined");
|
||||
ESP_ERROR_CHECK(1);
|
||||
}
|
||||
#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));
|
||||
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();
|
||||
|
|
@ -195,7 +179,8 @@ static void GSMInitTask(void *pvParameter)
|
|||
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);
|
||||
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();
|
||||
|
||||
|
|
@ -207,116 +192,133 @@ static void GSMInitTask(void *pvParameter)
|
|||
/* 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);
|
||||
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 GSMConnectTimeout = 0;
|
||||
while (esp_modem_get_module_name(dce, mod_info.model) != ESP_OK)
|
||||
{
|
||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
||||
|
||||
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);
|
||||
|
||||
// IMSI
|
||||
OperationRepeate = 0;
|
||||
mod_info.imsi[0] = 0x00;
|
||||
while (esp_modem_get_imsi(dce, mod_info.imsi) != ESP_OK)
|
||||
{
|
||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
||||
while (esp_modem_get_imsi(dce, mod_info.imsi) != ESP_OK) {
|
||||
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||
ESP_LOGE(TAG, "Error get IMSI");
|
||||
goto modem_init_fail;
|
||||
}
|
||||
ESP_LOGW(TAG, "Retry get IMSI");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
ESP_LOGI(TAG, "IMSI:%s", mod_info.imsi);
|
||||
|
||||
// OPERATOR NAME
|
||||
OperationRepeate = 0;
|
||||
mod_info.oper[0] = 0x00;
|
||||
int tech = 0;
|
||||
while (esp_modem_get_operator_name(dce, mod_info.oper, &tech) != ESP_OK)
|
||||
{
|
||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
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;
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
ESP_LOGW(TAG, "Retry get operator name");
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
}
|
||||
ESP_LOGI(TAG, "Operator:%s", mod_info.oper);
|
||||
|
||||
// IMEI
|
||||
mod_info.imei[0] = 0x00;
|
||||
while (esp_modem_get_imei(dce, mod_info.imei) != ESP_OK)
|
||||
{
|
||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
||||
OperationRepeate = 0;
|
||||
while (esp_modem_get_imei(dce, mod_info.imei) != ESP_OK) {
|
||||
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||
ESP_LOGE(TAG, "Error get IMEI");
|
||||
goto modem_init_fail;
|
||||
}
|
||||
ESP_LOGW(TAG, "Retry get IMEI");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
ESP_LOGI(TAG, "IMEI:%s", mod_info.imei);
|
||||
|
||||
while (esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX) != ESP_OK)
|
||||
{
|
||||
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
|
||||
// SWITCH TO CMUX
|
||||
OperationRepeate = 0;
|
||||
while (esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX) != ESP_OK) {
|
||||
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
|
||||
ESP_LOGE(TAG, "Error switch module to CMUX");
|
||||
goto modem_init_fail;
|
||||
}
|
||||
ESP_LOGW(TAG, "Retry switch module to CMUX");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "PPP data mode OK");
|
||||
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
|
||||
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(WAIT_FOR_GET_IP * 1000));
|
||||
|
||||
isPPPinitializing = false;
|
||||
vTaskDelete(NULL);
|
||||
|
||||
return;
|
||||
modem_init_fail:
|
||||
ESP_LOGE(TAG, "PPP modem init error");
|
||||
ESP_LOGE(TAG, "PPP modem initialization fail");
|
||||
isPPPinitializing = false;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void PPPModemColdStart(void)
|
||||
{
|
||||
void PPPModemColdStart(void) {
|
||||
ResetType = 0;
|
||||
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
|
||||
xTaskCreatePinnedToCore(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3,
|
||||
&initTaskhandle, 1);
|
||||
ESP_LOGI(TAG, "Start GSM cold initialization task");
|
||||
}
|
||||
|
||||
void PPPModemSoftRestart(void)
|
||||
{
|
||||
void PPPModemSoftRestart(void) {
|
||||
ResetType = 1;
|
||||
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
|
||||
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3,
|
||||
&initTaskhandle);
|
||||
ESP_LOGI(TAG, "Start GSM soft initialization task");
|
||||
}
|
||||
|
||||
static void GSMRunTask(void *pvParameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!isPPPConn && !isPPPinitializing)
|
||||
{ //try to reconnect modem
|
||||
ESP_LOGI(TAG, "PPP modem restart");
|
||||
static void GSMRunTask(void *pvParameter) {
|
||||
while (1) {
|
||||
if (!isPPPConn && !isPPPinitializing) { // try to reconnect modem
|
||||
ESP_LOGW(TAG, "Module restart by watchdog");
|
||||
PPPModemColdStart();
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(30000));
|
||||
vTaskDelay(pdMS_TO_TICKS(WATCHDOG_INTERVAL * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
void PPPModemStart(void)
|
||||
{
|
||||
xTaskCreate(GSMRunTask, "GSMRunTask", 1024 * 4, &ResetType, 3, NULL);
|
||||
void PPPModemStart(void) {
|
||||
xTaskCreatePinnedToCore(GSMRunTask, "GSMRunTask", 1024 * 4, &ResetType, 3, NULL, 1);
|
||||
}
|
||||
|
||||
int PPPModemGetRSSI(void)
|
||||
{
|
||||
int PPPModemGetRSSI(void) {
|
||||
int rssi = -1, ber;
|
||||
if (isPPPConn)
|
||||
esp_modem_get_signal_quality(dce, &rssi, &ber);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
void ModemSetATTimeout(int timeout)
|
||||
{
|
||||
attimeout = timeout;
|
||||
}
|
||||
void ModemSetATTimeout(int timeout) { attimeout = timeout; }
|
||||
|
||||
void ModemSendAT(char *cmd, char *resp, int 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)
|
||||
{
|
||||
switch (res) {
|
||||
case 0:
|
||||
ESP_LOGI(TAG, "OK");
|
||||
break;
|
||||
|
|
@ -331,16 +333,11 @@ void ModemSendAT(char *cmd, char *resp, int timeout)
|
|||
ESP_LOGI(TAG, "Response:%s", resp);
|
||||
}
|
||||
|
||||
esp_err_t cmd_cb(uint8_t* data, int len)
|
||||
{
|
||||
esp_err_t cmd_cb(uint8_t *data, int len) {
|
||||
ESP_LOGI(TAG, "Response:%*s", len, data);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ModemSendSMS(void)
|
||||
{
|
||||
esp_modem_command(dce, "atd", &cmd_cb, 3000);
|
||||
}
|
||||
void ModemSendSMS(void) { esp_modem_command(dce, "atd", &cmd_cb, 3000); }
|
||||
|
||||
#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)
|
||||
{
|
||||
unsigned char pass[18] = { 0 }; //max length of login:password decoded string
|
||||
unsigned char inp[31]; //max length of login:password coded string plus Basic
|
||||
unsigned char pass[BASIC_DECODED_LENGTH] = { 0 }; //max length of login:password decoded string
|
||||
unsigned char inp[BASIC_ENCODED_LENGTH]; //max length of login:password coded string plus Basic
|
||||
const char keyword1[] = "Basic ";
|
||||
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_send_err(req, HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE, "Authorization field value is too large");
|
||||
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);
|
||||
if (pt)
|
||||
{
|
||||
|
|
@ -460,7 +465,11 @@ esp_err_t start_file_server(void)
|
|||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
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"));
|
||||
#endif
|
||||
server = start_webserver();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
|
|
|||
33
src/MQTT.c
33
src/MQTT.c
|
|
@ -28,17 +28,13 @@
|
|||
|
||||
#define TAG "MQTT"
|
||||
#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_MESSAGE_BUFER_LENTH 10 //size of mqtt queue
|
||||
#define MQTT_RECONNECT_CHANGE_ADAPTER 3
|
||||
|
||||
#define MQTT_RECONNECT_TIMEOUT 20
|
||||
#define MQTT_RECONNECT_TIMEOUT 10
|
||||
|
||||
#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, "/");
|
||||
strcat((char*) topic, GetSysConf()->mqttStation[idx].ClientID); // Device client name (for multiclient devices)
|
||||
strcat((char*) topic, "-");
|
||||
strcat((char*) topic, GetSysConf()->ID); //
|
||||
//strcat((char*) topic, "-");
|
||||
//strcat((char*) topic, GetSysConf()->ID); //
|
||||
strcat((char*) topic, "/");
|
||||
strcat((char*) topic, (const char*) service_name); // Device service name
|
||||
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);
|
||||
DSS.raw_data_ptr = buf;
|
||||
DSS.data_length = len;
|
||||
DSS.keep_memory_onfinish = false;
|
||||
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(0)) == pdPASS)
|
||||
return ESP_OK;
|
||||
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);
|
||||
#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
|
||||
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:
|
||||
|
||||
#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
|
||||
if (event->data_len == 0 || event->current_data_offset > 0) //possible fragments of long data
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
||||
{
|
||||
|
|
@ -406,7 +391,7 @@ void MQTTTaskTransmit(void *pvParameter)
|
|||
{
|
||||
|
||||
#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
|
||||
esp_mqtt_client_publish(mqtt[idx].mqtt,
|
||||
(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_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &reconnect_MQTT_handler, &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 "NetTransport.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "RawMemAPI.h"
|
||||
|
||||
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)
|
||||
{
|
||||
GetDefaultNetIFName(argres);
|
||||
char interface[3];
|
||||
GetDefaultNetIFName(interface);
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", interface);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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\"");
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
|
||||
void funct_gsm_module(char *argres, int rw)
|
||||
{
|
||||
|
|
@ -255,7 +269,6 @@ void funct_gsm_rssi(char *argres, int rw)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||
void funct_lora_stat(char *argres, int rw)
|
||||
{
|
||||
|
|
@ -283,7 +296,6 @@ void funct_lora_appkey(char *argres, int rw)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void funct_ota_state(char *argres, int rw)
|
||||
{
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", GetUpdateStatus());
|
||||
|
|
@ -301,50 +313,8 @@ static void funct_ota_newver(char *argres, int rw)
|
|||
//CRON implementation BEGIN
|
||||
static void funct_cronrecs(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);
|
||||
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));
|
||||
CronRecordsInterface(argres, rw);
|
||||
}
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (rw)
|
||||
ExecCommand(argres);
|
||||
else
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"EXECUTED\"");
|
||||
int res = ExecCommand(argres);
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", EXEC_ERROR[res]);
|
||||
}
|
||||
|
||||
static const char *dirpath = "/data/";
|
||||
|
||||
static void funct_file_list(char *argres, int rw)
|
||||
{
|
||||
|
||||
char entrypath[FILE_PATH_MAX];
|
||||
char entrysize[16];
|
||||
const char *entrytype = "file";
|
||||
struct dirent *entry;
|
||||
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;
|
||||
#if CONFIG_SDCARD_ENABLE
|
||||
FileListHandler(argres, rw, "/sdcard/");
|
||||
#else
|
||||
FileListHandler(argres, rw, "/data/");
|
||||
#endif
|
||||
}
|
||||
|
||||
struct jWriteControl jwc;
|
||||
jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT);
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
static void funct_file_block(char *argres, int rw)
|
||||
{
|
||||
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;
|
||||
#if CONFIG_SDCARD_ENABLE
|
||||
FileBlockHandler(argres, rw, "/sdcard/");
|
||||
#else
|
||||
FileBlockHandler(argres, rw, "/data/");
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
#if CONFIG_SDCARD_ENABLE
|
||||
static void funct_sd_list(char *argres, int rw)
|
||||
{
|
||||
char filepath[FILE_PATH_MAX];
|
||||
struct stat file_stat;
|
||||
const char *filename = argres;
|
||||
if (!filename)
|
||||
{
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
||||
return;
|
||||
FileListHandler(argres, rw, "/sdcard/");
|
||||
}
|
||||
|
||||
if (filename[strlen(filename) - 1] == '/')
|
||||
static void funct_sd_block(char *argres, int rw)
|
||||
{
|
||||
ESP_LOGE("FILE_API", "Invalid filename : %s", filename);
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
||||
return;
|
||||
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);
|
||||
}
|
||||
|
||||
strcpy(filepath, dirpath);
|
||||
strcat(filepath, filename);
|
||||
|
||||
ESP_LOGI("FILE_API", " filepath to delete : %s", filepath);
|
||||
|
||||
if (stat(filepath, &file_stat) == -1)
|
||||
static void funct_lon(char *argres, int rw)
|
||||
{
|
||||
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 (rw)
|
||||
{
|
||||
char filepath[FILE_PATH_MAX];
|
||||
struct stat file_stat;
|
||||
const char *filename = argres;
|
||||
if (!filename)
|
||||
{
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"ERROR:DIR_NOT_FOUND\"");
|
||||
return;
|
||||
GetSysConf()->sntpClient.lon = atof(argres);
|
||||
}
|
||||
|
||||
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_raw_data(char *argres, int rw)
|
||||
{
|
||||
RawDataHandler(argres, rw);
|
||||
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%f", GetSysConf()->sntpClient.lon);
|
||||
}
|
||||
|
||||
const int hw_rev = CONFIG_BOARD_HARDWARE_REVISION;
|
||||
|
|
@ -502,6 +406,7 @@ const rest_var_t SystemVariables[] =
|
|||
|
||||
{ 0, "exec", &funct_exec, VAR_FUNCT, RW, 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, "free_ram", &funct_fram, 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_opt", CONFIG_BOARD_HARDWARE_OPTION, VAR_STRING, R, 1, 256 },
|
||||
|
||||
|
||||
{ 0, "net_bios_name", &SysConfig.NetBIOSName, 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, "primary_color", CONFIG_WEBGUIAPP_ACCENT_COLOR, VAR_STRING, RW, 3, 31 },
|
||||
{ 0, "dark_theme", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
|
||||
|
||||
|
||||
{ 0, "ota_url", &SysConfig.OTAURL, VAR_STRING, RW, 3, 128 },
|
||||
{ 0, "ota_auto_int", &SysConfig.OTAAutoInt, VAR_INT, RW, 0, 65535 },
|
||||
{ 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_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
|
||||
{ 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 },
|
||||
|
|
@ -651,10 +557,9 @@ const rest_var_t SystemVariables[] =
|
|||
{ 0, "serial_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||
{ 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_appid", &funct_lora_appid, VAR_FUNCT, RW, 0, 0 },
|
||||
{ 0, "lora_appkey", &funct_lora_appkey, VAR_FUNCT, R, 0, 0 },
|
||||
|
|
@ -664,11 +569,6 @@ const rest_var_t SystemVariables[] =
|
|||
{ 0, "lora_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_WEBGUIAPP_MBTCP_ENABLED
|
||||
{ 0, "mbtcp_enab", &SysConfig.modbusSettings.IsModbusTCPEnabled, VAR_BOOL, RW, 0, 1 },
|
||||
{ 0, "mbtcp_port", &SysConfig.modbusSettings.ModbusTCPPort, VAR_INT, RW, 1, 65534 },
|
||||
|
|
@ -680,15 +580,17 @@ const rest_var_t SystemVariables[] =
|
|||
{ 0, "objsinfo", &funct_objsinfo, 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_get", &funct_file_get, VAR_FUNCT, R, 0, 0 },
|
||||
{ 0, "file_put", &funct_file_put, VAR_FUNCT, R, 0, 0 },
|
||||
|
||||
{ 0, "raw_data", &funct_raw_data, VAR_FUNCT, R, 0, 0 },
|
||||
{ 0, "file_block", &funct_file_block, VAR_FUNCT, R, 0, 0 },
|
||||
#if CONFIG_SDCARD_ENABLE
|
||||
{ 0, "sd_list", &funct_sd_list, VAR_FUNCT, R, 0, 0 },
|
||||
{ 0, "sd_block", &funct_sd_block, 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)
|
||||
{
|
||||
rest_var_t *V = NULL;
|
||||
|
|
@ -730,6 +632,12 @@ esp_err_t SetConfVar(char *name, char *val, rest_var_types *tp)
|
|||
else
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
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:
|
||||
constr = atoi(val);
|
||||
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:
|
||||
itoa(*((int*) V->ref), val, 10);
|
||||
break;
|
||||
case VAR_CHAR:
|
||||
itoa(*((uint8_t*) V->ref), val, 10);
|
||||
break;
|
||||
case VAR_STRING:
|
||||
strcpy(val, (char*) V->ref);
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
++UpTime;
|
||||
MidnightTimer();
|
||||
FileBlockTimeoutCounter();
|
||||
}
|
||||
|
||||
uint32_t GetUpTime(void)
|
||||
|
|
|
|||
|
|
@ -131,8 +131,8 @@ void serial_RX_task(void *arg)
|
|||
|
||||
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
|
||||
{
|
||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 0);
|
||||
ExternalServiceMQTTSend(rxbuf, buffered_size, 1);
|
||||
ExternalServiceMQTTSend(EXTERNAL_SERVICE_NAME, rxbuf, buffered_size, 0);
|
||||
ExternalServiceMQTTSend(EXTERNAL_SERVICE_NAME, rxbuf, buffered_size, 1);
|
||||
}
|
||||
else
|
||||
ReceiveHandlerAPI();
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
|
|||
jwObj_int(&jwc, "msgid", MSG->parsedData.msgID);
|
||||
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
|
||||
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
||||
char time[RFC3339_TIMESTAMP_LENGTH];
|
||||
GetRFC3339Time(time);
|
||||
char time[ISO8601_TIMESTAMP_LENGTH];
|
||||
GetISO8601Time(time);
|
||||
jwObj_string(&jwc, "time", time);
|
||||
jwObj_int(&jwc, "msgtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||
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_string(&jwc, "srcid", GetSysConf()->ID);
|
||||
jwObj_string(&jwc, "dstid", MSG->parsedData.srcID);
|
||||
char time[RFC3339_TIMESTAMP_LENGTH];
|
||||
GetRFC3339Time(time);
|
||||
char time[ISO8601_TIMESTAMP_LENGTH];
|
||||
GetISO8601Time(time);
|
||||
jwObj_string(&jwc, "time", time);
|
||||
jwObj_int(&jwc, "messtype", DATA_MESSAGE_TYPE_RESPONSE);
|
||||
const char *err_br;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ esp_err_t WebGuiAppInit(void)
|
|||
#if CONFIG_WEBGUIAPP_I2C_ENABLE
|
||||
InitSysI2C();
|
||||
#endif
|
||||
#if CONFIG_SDCARD_ENABLE
|
||||
InitSysSDCard();
|
||||
#endif
|
||||
|
||||
esp_err_t err = nvs_flash_init();
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
|
@ -157,6 +160,7 @@ esp_err_t WebGuiAppInit(void)
|
|||
/*Start services depends on client connection*/
|
||||
#if CONFIG_WEBGUIAPP_GPRS_ENABLE || CONFIG_WEBGUIAPP_ETHERNET_ENABLE || CONFIG_WEBGUIAPP_WIFI_ENABLE
|
||||
ESP_ERROR_CHECK(start_file_server());
|
||||
if (GetSysConf()->sntpClient.Flags1.bIsGlobalEnabled)
|
||||
StartTimeGet();
|
||||
//regTimeSyncCallback(&TimeObtainHandler);
|
||||
//mDNSServiceStart();
|
||||
|
|
@ -174,7 +178,6 @@ esp_err_t WebGuiAppInit(void)
|
|||
InitSerialPort();
|
||||
#endif
|
||||
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
memcpy(Conf->mqttStation[0].GroupName, 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,
|
||||
sizeof(CONFIG_WEBGUIAPP_MQTT_USERNAME));
|
||||
memcpy(Conf->mqttStation[0].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD,
|
||||
sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
||||
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
|
||||
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));
|
||||
Conf->mqttStation[1].ServerPort = CONFIG_WEBGUIAPP_MQTT_SERVER_PORT;
|
||||
memcpy(Conf->mqttStation[1].SystemName, 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].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].UserPass, CONFIG_WEBGUIAPP_MQTT_PASSWORD, sizeof(CONFIG_WEBGUIAPP_MQTT_PASSWORD));
|
||||
#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));
|
||||
Conf->sntpClient.Flags1.bIsGlobalEnabled = CONFIG_WEBGUIAPP_SNTP_AUTOUPDATE_ENABLE;
|
||||
Conf->sntpClient.TimeZone = CONFIG_WEBGUIAPP_SNTP_TIMEZONE;
|
||||
Conf->sntpClient.lat = 0.0;
|
||||
Conf->sntpClient.lon = 0.0;
|
||||
|
||||
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
|
||||
Conf->lorawanSettings.Flags1.bIsLoRaWANEnabled = true;
|
||||
|
|
@ -430,11 +441,17 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
|
|||
Conf->Timers[i].del = true;
|
||||
Conf->Timers[i].enab = 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].cron, "* * * * * *");
|
||||
strcpy(Conf->Timers[i].exec, "OBJECT,ACTION,ARGUMENTS");
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WEBGUIAPP_ASTRO_ENABLE
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t ReadNVSSysConfig(SYS_CONFIG *SysConf)
|
||||
|
|
@ -575,6 +592,70 @@ void SetUserAppNeedReset(bool 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, ...)
|
||||
{
|
||||
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
|
||||
* value is same as that set in file_server.c */
|
||||
var MAX_FILE_SIZE = 1000*1024;
|
||||
var MAX_FILE_SIZE_STR = "1MB";
|
||||
var MAX_FILE_SIZE = 100*1000*1024;
|
||||
var MAX_FILE_SIZE_STR = "100MB";
|
||||
|
||||
if (fileInput.length == 0) {
|
||||
alert("No file selected!");
|
||||
|
|
@ -46,8 +46,8 @@ function upload() {
|
|||
alert("File path on server cannot have spaces!");
|
||||
} else if (filePath[filePath.length-1] == '/') {
|
||||
alert("File name not specified after path!");
|
||||
} else if (fileInput[0].size > 1000*1024) {
|
||||
alert("File size must be less than 1MB!");
|
||||
} else if (fileInput[0].size > MAX_FILE_SIZE) {
|
||||
alert("File size must be less than 100MB!");
|
||||
} else {
|
||||
document.getElementById("newfile").disabled = true;
|
||||
document.getElementById("filepath").disabled = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user