Compare commits

...

133 Commits

Author SHA1 Message Date
370f791151 fixed minor incompatibilities with idf 5.4 version 2025-05-11 12:49:02 +02:00
9585559ab7 shift register added to the component 2025-04-18 17:51:42 +02:00
45284cb4db disable error fields in protocol response message if no errors 2025-04-13 11:23:21 +02:00
65c790ea8e fixed baud rate setting affected on not own uart 2025-04-09 15:23:53 +02:00
19a9a46b2c fixed serial port access while port is disabled 2025-04-01 11:53:45 +02:00
27e87e4083 rollback expected max data size to fix file transfer operations 2025-03-26 18:55:03 +02:00
9b807179f9 fixed disable serial port function 2025-03-19 10:03:24 +02:00
2a6f6233af fixed uart tx disabled 2025-03-19 09:39:02 +02:00
b52dcdc5d8 pppos control 2025-03-14 19:21:58 +02:00
d254ff5c46 MQTT test message memory optimisation 2025-02-25 18:59:18 +02:00
a162ef8091 added modem reset on many mqtt retry, added reboot and modem reset to
command interface, pppos control from config
2025-02-22 16:34:15 +02:00
ea5bad2c1d fixed memory allocation for ISO8601 time record 2025-02-18 14:21:16 +02:00
915e6aa7c5 added experemental PPPoS 2025-02-17 18:47:04 +02:00
490fd3bfa4 extended log time format changed to ISO8601 2025-02-05 10:38:59 +02:00
0687a6a981 payload name added to the transport protocol 2025-01-24 13:26:31 +02:00
94af947d1f serial port settings fixed 2025-01-23 20:10:39 +02:00
e8e8876686 wifi reconnect policy improved, default uart settings restored 2025-01-23 14:00:39 +02:00
2547be508c fixed null argument in cron and exec commands 2024-12-28 22:43:27 +02:00
ca082595d9 cron global switch added 2024-12-12 17:29:49 +02:00
bogd
56d568954c fixed duplicate part of MQTT id 2024-09-27 16:08:04 +02:00
bogd
897ee0fec2 extend test message content 2024-08-29 12:28:19 +02:00
bogd
479b8968e1 mqtt test message is wrapped into generic protocol 2024-08-28 16:13:47 +02:00
bogd
dcd659e5ea added serial port settings 2024-08-26 16:10:21 +02:00
bogd
147c2b9cdd reset transaction on file delete error 2024-07-17 15:03:03 +02:00
bogd
8a1027a408 Merge remote-tracking branch 'gitlab/main' into main 2024-07-16 08:59:01 +02:00
b7ec9c8c35 fixed delete file after transid 2024-07-15 14:03:48 +02:00
bogd
a95e66c4b5 disabled debug block transfer 2024-07-08 11:12:20 +02:00
9b10a7f23d disabled debug of system log file operations 2024-07-07 14:39:02 +02:00
bc0660ef35 system log settings added to global configuration 2024-07-07 14:33:21 +02:00
26e104afe5 implemented system log with file rotation 2024-07-07 13:22:46 +02:00
bogd
0edc230a47 running GSM start task on core 1 to prevent uart irq allocate fail 2024-07-03 14:25:29 +02:00
bogd
d58ce6af9c file block transfer mechanism lock for first client, timeout of transfer
implemented
2024-07-02 12:40:25 +02:00
bogd
a1f7694bdb added transition id into block transfer module 2024-07-02 10:55:45 +02:00
bogd
3fe41b0f2e Merge remote-tracking branch 'gitlab/main' into main 2024-07-01 15:31:03 +02:00
bogd
44d7c8d539 fix infinit wait for get IP in GSM modem 2024-07-01 15:25:32 +02:00
b706e5ab26 resolved coflict with 'exec' variables handler 2024-06-25 13:38:26 +02:00
bogd
b8f649b371 conditional build of eeprom driver 2024-06-25 13:29:37 +02:00
7058e86538 implemented extended errors return for 'exec' variable 2024-06-24 21:29:58 +02:00
bogd
775635019c check eeprom ready before read, disabled debug messages in eeprom driver 2024-06-24 14:36:16 +02:00
bogd
f48880e78a eeprom block write debug 2024-06-21 16:31:02 +02:00
9276d4a6c1 implemented EEPROM write operation with data overlapped page size margin 2024-06-20 21:12:52 +02:00
bogd
6cb5bc0e9c start implementation i2c eeprom driver 2024-06-20 16:22:05 +02:00
0edd07fbd2 second MQTT always off for reduce memory consumption 2024-06-10 19:39:08 +02:00
bogd
0a21101817 fixed default interface variable output 2024-05-30 12:56:41 +02:00
bogd
8b8ea9a57f added CHAR type to the variables 2024-05-29 15:58:30 +02:00
bogd
a7417df420 gsm interface speed back to 115200, increased gsm commands attempts 2024-05-27 13:40:03 +02:00
394a798a98 fixed crash on modem restart during info retrieve over web ui 2024-05-23 09:54:36 +02:00
9f20a1b08b MQTT services definitions moved to mqtt header 2024-05-16 21:12:49 +02:00
92a1cc3cc7 astro timers implemented 2024-05-16 14:23:35 +02:00
513c9f6b89 astro timer combined with cron 2024-05-15 15:49:55 +02:00
3609a28892 astro data return after save 2024-05-15 08:21:06 +02:00
7346de2bdf astro data backend implemented 2024-05-14 17:07:26 +02:00
96a7238065 astro handle added 2024-05-14 10:54:05 +02:00
298c2e6534 astronomical calculations moved from double to float 2024-05-14 10:50:17 +02:00
a64de4a0c5 Astro timer moved to CRON scheduler 2024-05-14 10:28:59 +02:00
9d54a977fc added build config for astro timer 2024-05-13 15:57:25 +02:00
a9b4f515d5 added astro calculation core code 2024-05-13 15:36:19 +02:00
f0a773b53f added manual time set, fixed SNTP client disable 2024-05-13 12:47:40 +02:00
cda4bc7722 Merge branch 'main_sdcard' into 'main'
Main sdcard

See merge request userbogd/webguiapp!6
2024-05-08 14:43:23 +00:00
cef4def7f5 fixed basic auth header 2024-05-08 15:26:36 +02:00
c9beeaa39c SD card, if selected in build config, replacing internal storage 2024-05-08 10:24:42 +02:00
8e2490bef0 Merge branch 'main_sdcard' into 'main'
added SD card support

See merge request userbogd/webguiapp!5
2024-05-07 12:14:36 +00:00
4eaaff65fd added SD card support 2024-05-07 14:12:46 +02:00
94ff29e312 MQTT ID now is fully user defined 2024-04-30 09:46:58 +02:00
428bb65c7b time sync sequence improved 2024-04-27 12:21:41 +02:00
27cbfffb5b custom modem interaction baudrate set to 230 kbit/s 2024-04-24 14:59:26 +02:00
78dbc8e917 added SetSystemTime() function 2024-04-24 12:45:37 +02:00
3a7bf2a635 fixed GSM modem initialization sequence 2024-04-23 11:27:26 +02:00
3858722cca GSM external reset function delay 2024-04-11 16:02:30 +02:00
4fdec54608 timestamp format changed to ISO8601 2024-04-05 12:53:10 +02:00
db5452fe8b rollback mqtt reconnect time, added debug for receive mqtt data 2024-04-04 14:48:20 +02:00
2d8e4ee592 fixed lora visibility variable, tune mqtt timeouts, removes file topic 2024-04-03 14:26:25 +02:00
b473c8f198 fixed size of file block checking 2024-03-29 10:00:19 +02:00
25feb4f9fb export block_transaction_t object and it's parse function 2024-03-28 12:34:57 +02:00
83ab4dcba2 file api interface refactored 2024-03-28 12:08:49 +02:00
ec5069c096 reworked file api handler 2024-03-28 11:41:34 +02:00
84257e8276 documented raw memory access structure 2024-03-25 08:54:41 +02:00
9b11542f1a implemented file API in general protocol 2024-03-24 20:10:58 +02:00
5aaa2004c3 file read write API implemented 2024-03-13 19:51:11 +02:00
8f5537fd6a added file read write 2024-03-13 13:47:42 +02:00
086e919e23 added header for base64 encode decode 2024-03-12 20:09:21 +02:00
c32accd232 raw memory access API implementation 2024-03-12 19:54:20 +02:00
06ecf10ae5 prepare to implementation files API 2024-03-12 14:24:59 +02:00
981440adda mqtt file handler added 2024-03-11 15:40:48 +02:00
6712ed4b42 added topic for the files operations, file list and delete implemented 2024-03-11 14:41:32 +02:00
f007f15313 changed timestamp format in LogFile 2024-03-03 10:52:33 +02:00
2996e4175d Queue in MQTT transport wait for connected 2024-02-27 13:22:15 +02:00
65b977f089 fixed reset after OTA, added gsm level 2024-02-22 15:23:27 +02:00
369b236549 fixed memory leak in MQTT extended log 2024-02-22 12:18:00 +02:00
133dc249c7 Merge remote-tracking branch 'gitlab/main2' into main2 2024-02-21 14:18:03 +02:00
62ce254d47 Explicitly trimming long log messages 2024-02-21 14:15:40 +02:00
89cddc53a3 reconnect timeout in AP and STA changed 2024-02-20 11:47:17 +02:00
89d33842ec temporal solution of AP and STA coexistence 2024-02-19 16:14:25 +02:00
d7d38b1524 fixed redundant state callback in AP plus STA mode 2024-02-18 13:03:59 +02:00
6c20a210f9 fixed content type for dynamic resources, added for test modem command
with callback
2024-02-04 17:53:53 +02:00
a0ec795652 file storage web page improved design 2024-02-03 19:34:51 +02:00
351876cbb6 modem AT commands tested 2024-02-02 16:03:04 +02:00
da7e90bc82 added modem AT commands access 2024-02-02 09:04:44 +02:00
0603610229 added modem to mqtt bridge service 2024-02-01 09:07:59 +02:00
60f36fbf04 multipart large MQTT data fixed 2024-01-31 20:51:13 +02:00
aaed490d84 added free memory flag to MQTT transmit data structure 2024-01-30 14:52:05 +02:00
33da14fa0c update webguiapp submodules 2024-01-23 23:17:50 +02:00
37e74d3517 Merge remote-tracking branch 'gitlab/main2' into main2 2024-01-23 20:20:21 +02:00
b1311d8494 added timestamp in ISO-8601 format 2024-01-23 14:22:31 +02:00
f81358c5ec update components 2024-01-22 19:54:54 +02:00
f48de3aa15 hw_opt variable moved to application 2024-01-09 15:19:23 +02:00
096cb60633 added setting for delayed AP disable 2023-12-28 22:07:31 +02:00
114321c91b added user application HTTP handler with dedicated URI 2023-12-21 13:55:23 +02:00
5ebff8842e fixed gprs default state after clear config 2023-12-19 19:39:26 +02:00
83f97e9ac8 network adapter info for GSM fixed 2023-12-15 17:59:51 +02:00
f49d7c94fd APN setting added to gsm transport 2023-12-08 10:31:28 +02:00
d1a1759f01 disable more debug level 0 messages 2023-12-07 15:55:33 +02:00
580d92f9b5 added file server log level 2023-12-07 15:44:38 +02:00
9fbb16a5db overwrite files in storage partition, cron log file switche off 2023-12-07 13:30:19 +02:00
f2448d6dc3 fixed passing uart num to gsm driver 2023-12-05 16:24:13 +02:00
78e66bdf5f fixed POST multipacket data handler 2023-11-29 17:51:59 +02:00
e4783cba1d modem's uart buffer size ranges extended 2023-11-24 15:45:34 +02:00
0f371b6abc fixed MQTT send stack overflow on disconnected socket, no keep messages 2023-11-24 12:27:58 +02:00
5151cfc0f6 fixed ExtendedLog mqtt queue 2023-11-22 16:17:29 +02:00
4eb2456feb fixed in kconfig range of GPRS modem pins 2023-11-20 12:05:14 +02:00
4646d418c0 fixed argument in mqtt subcribe function for esp-idf 5.1.2 compatibility 2023-11-17 10:26:03 +02:00
9ca0d153de file size for upload to storage increased to 1 MB 2023-10-31 20:03:54 +02:00
51213d819c no read after write for type VAR_FUNCT, where needed it mast be done
manually
2023-10-30 16:04:54 +02:00
0521b8daff fixed variable write return error not a string 2023-10-27 14:49:00 +02:00
6ee55e363a unused colors settings removed from the build configuration 2023-10-27 11:41:36 +02:00
f1dfe3708e added hw option, moved serial port mode to build configuration 2023-10-25 13:01:05 +02:00
9116052ecb added basic authorization to the POST requests, removed var zize
definitions from old API
2023-10-24 12:39:20 +02:00
490bf91161 debug messages optimized in http and cron 2023-10-24 11:16:37 +02:00
e6b67333df fixed double response to the POST request 2023-10-23 20:20:02 +02:00
6b45b75e2e fixed serial port settings save command 2023-10-23 12:45:07 +02:00
3233d823d0 gzip content checking while give out file,
connection close on post JSON
2023-10-22 11:33:58 +02:00
3244ac8eb9 removed unused callbacks 2023-10-22 10:49:02 +02:00
b4cb524ea1 clean from old post get handlers 2023-10-22 10:27:01 +02:00
35 changed files with 2617 additions and 2529 deletions

View File

@ -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,10 +25,15 @@ idf_component_register(
"src/MQTT.c"
"src/CronTimers.c"
"src/SerialPort.c"
src/PPPoS.c
src/ShiftRegisterSPI.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}
@ -46,6 +49,7 @@ idf_component_register(
REQUIRES nvs_flash
spiffs
fatfs
esp_http_server
mbedtls
lwip

182
Kconfig
View File

@ -15,11 +15,15 @@ menu "WebGUIApp"
config BOARD_HARDWARE_REVISION
int "Board hardware revision"
range 1 5
default 1
default 1
config BOARD_HARDWARE_OPTION
string "Board hardware option"
default "DEFAULT"
config APP_PROJECT_VER
string "Device firmware version"
default "0.0.0.0000"
default "0.0.0.0"
help
Project version code
@ -70,38 +74,6 @@ menu "WebGUIApp"
default "#dba617"
help
Set accent color for user web ui
config WEBGUIAPP_SCH1_BACKGROUNG_COLOR
string "Scheme 1 background color"
default "#e0e0dd"
config WEBGUIAPP_SCH1_PANEL_COLOR
string "Scheme 1 panel background color"
default "#f0f0ed"
config WEBGUIAPP_SCH1_MENU_COLOR
string "Scheme 1 menu background color"
default "#ededea"
config WEBGUIAPP_SCH1_TEXT_COLOR
string "Scheme 1 font color"
default "#404040"
config WEBGUIAPP_SCH1_BORDER_COLOR
string "Scheme 1 border color"
default "#00000066"
config WEBGUIAPP_SCH2_BACKGROUNG_COLOR
string "Scheme 2 background color"
default "#1D2327"
config WEBGUIAPP_SCH2_PANEL_COLOR
string "Scheme 2 panel background color"
default "#2c3338"
config WEBGUIAPP_SCH2_MENU_COLOR
string "Scheme 2 menu background color"
default "#3c434a"
config WEBGUIAPP_SCH2_TEXT_COLOR
string "Scheme 2 font color"
default "#F0F0F0"
config WEBGUIAPP_SCH2_BORDER_COLOR
string "Scheme 2 border color"
default "#ffffff66"
endmenu
@ -116,7 +88,7 @@ menu "WebGUIApp"
config WEBGUIAPP_OTA_HOST
string "URL of firmware for OTA update"
default "https://iotronic.cloud/firmware/firmware.bin"
default "https://openergy.ru/firmware/firmware.bin"
help
URL of firmware file for OTA update
@ -208,7 +180,7 @@ menu "WebGUIApp"
endif
endmenu
menu "SPI settings"
config WEBGUIAPP_SPI_ENABLE
bool "Enabled SPI interface"
@ -288,6 +260,57 @@ menu "WebGUIApp"
endif
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"
@ -590,6 +613,10 @@ menu "WebGUIApp"
Set enabled GPRS adapter
if WEBGUIAPP_GPRS_ENABLE
config WEBGUIAPP_MODEM_AT_ACCESS
bool "Enable modem AT commands access"
default n
config WEBGUIAPP_GPRS_ON
bool "Default GPRS switched on"
@ -598,7 +625,7 @@ menu "WebGUIApp"
config MODEM_DEVICE_POWER_CONTROL_PIN
int "Power control GPIO"
default -1
range -1 33
range -1 GPIO_RANGE_MAX
help
Pin number of power control.
@ -673,28 +700,28 @@ menu "WebGUIApp"
config MODEM_UART_TX_PIN
int "TXD Pin Number"
default 17
range 0 33
range 0 GPIO_RANGE_MAX
help
Pin number of UART TX.
config MODEM_UART_RX_PIN
int "RXD Pin Number"
default 16
range 0 39
range 0 GPIO_RANGE_MAX
help
Pin number of UART RX.
config MODEM_UART_RTS_PIN
int "RTS Pin Number"
default 0
range 0 31
range 0 GPIO_RANGE_MAX
help
Pin number of UART RTS.
config MODEM_UART_CTS_PIN
int "CTS Pin Number"
default 0
range 0 31
range 0 GPIO_RANGE_MAX
help
Pin number of UART CTS.
@ -728,14 +755,14 @@ menu "WebGUIApp"
config MODEM_UART_TX_BUFFER_SIZE
int "UART TX Buffer Size"
range 256 2048
range 256 8192
default 512
help
Buffer size of UART TX buffer.
config MODEM_UART_RX_BUFFER_SIZE
int "UART RX Buffer Size"
range 256 2048
range 256 8192
default 1024
help
Buffer size of UART RX buffer.
@ -785,6 +812,48 @@ menu "WebGUIApp"
endif
endmenu
menu "PPPoS configuration"
config WEBGUIAPP_PPPOS_ENABLE
bool "Enabled PPPoS transport"
default n
endmenu
menu "SR IO extender configuration"
config WEBGUIAPP_SR_ENABLE
bool "Enabled SR IO extender"
default n
config WEBGUIAPP_SR_CLOCK_MHZ
int "SR extender clock speed (MHz)"
range 1 20
default 10 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32C3
default 30 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help
Set the clock speed (MHz) of SPI interface.
config WEBGUIAPP_SR_CS
int "SR SC signal GPIO"
range GPIO_RANGE_MIN GPIO_RANGE_MAX
default 12
help
Set GPIO for chip select signal.
config WEBGUIAPP_SR_OUTPUTS
int "SR outputs number"
range 0 64
default 8
help
Set the number of outputs (must be a multiple of 8).
config WEBGUIAPP_SR_INPUTS
int "SR inputs number"
range 0 64
default 8
help
Set the number of inputs (must be a multiple of 8).
endmenu
menu "Serial port configuration"
config WEBGUIAPP_UART_TRANSPORT_ENABLE
@ -814,6 +883,19 @@ menu "WebGUIApp"
help
Switch on bridge uart to mqtt, else uart operate same way as rest and mqtt data exchange
choice WEBGUIAPP_UART_MODE
prompt "Serial port mode"
default WEBGUIAPP_UART_MODE_UART
help
Select serial port mode.
config WEBGUIAPP_UART_MODE_UART
bool "UART"
config WEBGUIAPP_UART_MODE_RS485
bool "RS485"
endchoice
config WEBGUIAPP_UART_BAUD_RATE
int "UART communication speed"
range 1200 115200
@ -876,8 +958,6 @@ menu "WebGUIApp"
endif
endmenu
menu "MQTT settings"
config WEBGUIAPP_MQTT_ENABLE
bool "Enabled MQTT transport"
@ -941,6 +1021,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"

View File

@ -39,8 +39,8 @@ int ExecCommand(char *cmd);
void GetObjectsInfo(char *data);
void SetCustomObjects(obj_struct_t *obj);
obj_struct_t* GetSystemObjects();
obj_struct_t* GetCustomObjects();
const obj_struct_t* GetSystemObjects();
const obj_struct_t* GetCustomObjects();

View File

@ -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_ */

View File

@ -43,20 +43,17 @@
#include "mbedtls/base64.h"
#include "SystemApplication.h"
#define MAX_DYNVAR_NAME_LENGTH 32
#define MAX_DYNVAR_LENGTH 256
#define MAX_INCFILE_LENGTH 1024
/* 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 (200*1024) // 200 KB
#define MAX_FILE_SIZE_STR "200KB"
#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
#define AUTH_DATA_MAX_LENGTH 16
#define HTTP_SERVER_DEBUG_LEVEL 0
#define FILE_SERVER_DEBUG_LEVEL 0
typedef enum
{
@ -87,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);
@ -96,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_ */

View File

@ -47,11 +47,22 @@ 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
#define MQTT1 0
#define MQTT2 1
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
typedef struct
{
char topic[CONFIG_WEBGUIAPP_MQTT_MAX_TOPIC_LENGTH];
char *raw_data_ptr;
int data_length;
bool keep_memory_onfinish;
}MQTT_DATA_SEND_STRUCT;
/**
@ -76,6 +87,8 @@ void ComposeTopic(char *topic, int idx, char *service_name, char *direct);
void SystemDataHandler(char *data, uint32_t len, int idx);
mqtt_app_err_t PublicTestMQTT(int idx);
esp_err_t ExternalServiceMQTTSend(char *data, int len, int idx);
esp_err_t ExternalServiceMQTTSend(char *servname, char *data, int len, int idx);
#endif
#endif /* MAIN_INCLUDE_MQTT_H_ */

View File

@ -46,6 +46,7 @@ typedef struct
#define AP_PRIO 10
#define RFC3339_TIMESTAMP_LENGTH (26)
#define ISO8601_TIMESTAMP_LENGTH (32)
//#define DEFAULT_FALLBACK_DNS "8.8.8.8"
@ -72,6 +73,7 @@ void EthStart(void);
void WiFiTransportTask(void *prm);
void PPPConnReset (void);
void PPPModemColdStart(void);
void PPPModemSoftRestart(void);
@ -80,6 +82,7 @@ void PPPModemStart(void);
int PPPModemGetRSSI(void);
void ModemSendSMS(void);
void ModemSendAT(char *cmd, char *resp, int timeout);
void ModemSetATTimeout(int timeout);
void MQTTRun(void);
@ -94,6 +97,7 @@ esp_netif_t* GetSTANetifAdapter(void);
esp_netif_t* GetAPNetifAdapter(void);
esp_netif_t* GetETHNetifAdapter(void);
bool isWIFIConnected(void);
bool isETHConnected(void);
bool isPPPConnected(void);
@ -113,7 +117,10 @@ void PrintNetifs(void);
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();

View File

@ -0,0 +1,51 @@
/*
* ShiftRegisterSPI.h
*
* Created on: Apr 18, 2025
* Author: bogd
*/
#ifndef COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_
#define COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_
#include "esp_err.h"
typedef enum {
VGPIO_NUM_NC = -1,
VGPIO_NUM_0 = 0,
VGPIO_NUM_1 = 1,
VGPIO_NUM_2 = 2,
VGPIO_NUM_3 = 3,
VGPIO_NUM_4 = 4,
VGPIO_NUM_5 = 5,
VGPIO_NUM_6 = 6,
VGPIO_NUM_7 = 7,
VGPIO_NUM_MAX,
/** @endcond */
} virtual_gpio_num_t;
typedef enum {
VGPIO_MOTOR_IN1 = 0,
VGPIO_MOTOR_IN2,
VGPIO_PILOT_RELAY,
VGPIO_RELAY1,
VGPIO_RELAY2,
VGPIO_TRIAC1,
VGPIO_TRIAC2,
VGPIO_TRIAC3
} virtual_gpio_funct_t;
esp_err_t ShiftRegInit(void);
esp_err_t vgpio_set_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level);
esp_err_t vgpio_get_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level);
esp_err_t vgpi_get_level(int gpio_num, uint8_t *gpio_level);
esp_err_t vgpio_set_reg(uint8_t reg);
void GPIOExtenderTxRx(uint8_t *tx, uint8_t *rx, int bt);
void GPIOInputRead(int num, int *val);
void GPIOInputWrite(int num, int *val);
#endif /* COMPONENTS_WEBGUIAPP_INCLUDE_SHIFTREGISTERSPI_H_ */

View File

@ -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
@ -167,7 +171,8 @@ typedef struct
bool bIsDHCPEnabled;
bool bIsWiFiEnabled;
} Flags1; // Flag structure
uint8_t MaxPower;
int MaxPower;
int AP_disab_time;
} wifiSettings;
#endif
@ -186,6 +191,10 @@ typedef struct
bool bIsGSMEnabled;
} Flags1; // Flag structure
char APN[32];
char login[32];
char password[32];
} gsmSettings;
#endif
@ -195,6 +204,9 @@ typedef struct
{
int Serialmode;
int BaudRate;
int DataBits;
int Parity;
int StopBits;
int InputBrake;
struct
{
@ -226,8 +238,9 @@ typedef struct
} modbusSettings;
cron_timer_t Timers[CONFIG_WEBGUIAPP_CRON_NUMBER];
bool bIsCRONEnabled;
} SYS_CONFIG;

View File

@ -30,12 +30,9 @@
#define REAST_API_DEBUG_MODE 0
#define EXPECTED_MAX_HEADER_SIZE 512
#define EXPECTED_MAX_PAYLOAD_SIZE 4096
#define EXPECTED_MAX_DATA_SIZE (EXPECTED_MAX_HEADER_SIZE + EXPECTED_MAX_PAYLOAD_SIZE)
#define VAR_MAX_NAME_LENGTH MAX_DYNVAR_NAME_LENGTH
#define VAR_MAX_VALUE_LENGTH (2048)
#define EXPECTED_MAX_DATA_SIZE (4096 * 2)
#define VAR_MAX_NAME_LENGTH (32)
#define VAR_MAX_VALUE_LENGTH (EXPECTED_MAX_DATA_SIZE - 512)
#define PAYLOAD_ERROR 0
#define PAYLOAD_DEFAULT 1
@ -101,6 +98,7 @@ typedef struct
time_t time;
int msgType;
int payloadType;
char payloadName[32];
void *payload;
unsigned char sha256[32];
} parsedData;
@ -114,6 +112,8 @@ typedef struct
}UART_DATA_SEND_STRUCT;
void InitSerialPort(void);
void InitPPPSerial();
void InitSysSDCard();
esp_err_t TransmitSerialPort(char *data, int ln);
esp_err_t GetConfVar(char* name, char* val, rest_var_types *tp);
@ -123,4 +123,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_ */

View File

@ -33,11 +33,11 @@ void regHookBeforeUpdate(void (*before_update)(void));
//MQTT incoming data callback
void regUserEventHandler(void (*event_handler)(int idx, void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data), void* user_arg);
//User handler of output '~var~' styled dynamic variables. Calls on give out files in response to GET requests.
void regHTTPPrintCustom(int (*print_handler)(httpd_req_t *req, char *buf, char *var, int arg));
//User App POST GET handlers register and set URL for this handlers
void regHTTPUserAppHandlers(char *url,
esp_err_t (*get)(httpd_req_t *req),
esp_err_t (*post)(httpd_req_t *req));
//User handler of variables 'var1=value1&var2=value2' styled in POST requests.
void regAfterPostHandlerCustom(HTTP_IO_RESULT (*post_handler)(httpd_req_t *req, const char *filename, char *PostData));
//User handler for various payload types
void regCustomPayloadTypeHandler(sys_error_code (*payload_handler)(data_message_t *MSG));

View File

@ -35,6 +35,7 @@
#include "SystemApplication.h"
#include "UserCallbacks.h"
#include "CommandProcSys.h"
#include "ShiftRegisterSPI.h"
esp_err_t spi_device_polling_transmit_synchronized(spi_device_handle_t handle, spi_transaction_t *trans_desc);
@ -42,5 +43,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_ */

View File

@ -20,8 +20,10 @@
*/
#include "CommandProcSys.h"
#include "NetTransport.h"
#include "webguiapp.h"
#define TAG "COMMAND_PROC_SYS"
//#define MAX_OBJECTS_NUMBER CONFIG_WEBGUIAPP_MAX_OBJECTS_NUM
@ -34,7 +36,8 @@ const char *exec_errors[] = {
"param COMMAND not found",
"object not exists",
"command not exists",
"handler not set"
"handler not set",
"param ARGUMENT not found",
};
@ -47,6 +50,14 @@ static void SYSTEM_TEST_handle(char *obj, char *com, char *arg)
static void SYSTEM_REBOOT_handle(char *obj, char *com, char *arg)
{
ESP_LOGI(TAG, "Object:%s, Command:%s, Argument %s", obj, com, arg);
esp_restart();
}
static void MODEM_REBOOT_handle(char *obj, char *com, char *arg)
{
ESP_LOGI(TAG, "Object:%s, Command:%s, Argument %s", obj, com, arg);
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
PPPConnReset();
#endif
}
obj_struct_t *custom_com_obj_arr = NULL;
@ -64,9 +75,9 @@ const obj_struct_t com_obj_arr[] = {
},
{
.index = 0,
.object_name = "SYSTEM1",
.object_name = "MODEM",
.allowed_actions = { "TEST", "REBOOT", "TEST2", "TEST3", "TEST4" },
.command_handlers = { &SYSTEM_TEST_handle, &SYSTEM_REBOOT_handle }
.command_handlers = { &SYSTEM_TEST_handle, &MODEM_REBOOT_handle }
},
{
.index = 0,
@ -83,12 +94,12 @@ const obj_struct_t com_obj_arr[] = {
{ 0 }
};
obj_struct_t* GetSystemObjects()
const obj_struct_t* GetSystemObjects()
{
return &com_obj_arr;
return (obj_struct_t*)&com_obj_arr;
}
obj_struct_t* GetCustomObjects()
const obj_struct_t* GetCustomObjects()
{
return custom_com_obj_arr;
}
@ -144,10 +155,10 @@ int ExecCommand(char *cmd)
static int ExecCommandParse(char *cmd)
{
char *obj = NULL, *com = NULL, *arg = NULL;
int err = 0;
//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 +166,11 @@ 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
if (!arg)
return 7; //ERROR_ACTION_NOT_PARSED
for (int idx = 0; idx < CONFIG_WEBGUIAPP_MAX_OBJECTS_NUM; idx++)
{
@ -170,13 +183,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 +204,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
}

View File

@ -20,15 +20,22 @@
*/
#include <CronTimers.h>
#include "SysConfiguration.h"
#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;
@ -36,13 +43,8 @@ char* GetCronError()
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;
if (GetSysConf()->bIsCRONEnabled)
ExecCommand(((cron_timer_t*) job->data)->exec);
}
const char* check_expr(const char *expr)
@ -69,9 +71,6 @@ static void ExecuteLastAction(obj_struct_t *objarr)
char *obj = objarr[obj_idx].object_name;
if (*obj == '\0')
break;
//ESP_LOGI(TAG, "Check object %s", obj);
for (shdl = 0; shdl < CRON_TIMERS_NUMBER; shdl++)
{
memcpy(objname, GetSysConf()->Timers[shdl].exec, CONFIG_WEBGUIAPP_MAX_COMMAND_STRING_LENGTH / 4);
@ -98,8 +97,9 @@ static void ExecuteLastAction(obj_struct_t *objarr)
if (minimal != -1)
{
ESP_LOGW(TAG, "Run previous CRON \"%s\" with delta %d", GetSysConf()->Timers[minimal].exec, (int )delta);
ExecCommand(GetSysConf()->Timers[minimal].exec);
ESP_LOGI(TAG, "Run previous CRON \"%s\" with delta %d", GetSysConf()->Timers[minimal].exec, (int )delta);
if (GetSysConf()->bIsCRONEnabled)
ExecCommand(GetSysConf()->Timers[minimal].exec);
}
}
@ -107,11 +107,12 @@ static void ExecuteLastAction(obj_struct_t *objarr)
void TimeObtainHandler(struct timeval *tm)
{
ESP_LOGW(TAG, "Current time received with value %d", (unsigned int )tm->tv_sec);
ESP_LOGI(TAG, "Current time updated with value %d", (unsigned int )tm->tv_sec);
RecalcAstro(tm->tv_sec);
ReloadCronSheduler();
ExecuteLastAction(GetSystemObjects());
ExecuteLastAction(GetCustomObjects());
LogFile("cron.log", "Cron service started");
}
void DebugTimer()
@ -153,3 +154,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
View 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
View 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);
}

View File

@ -70,6 +70,10 @@ static esp_err_t set_content_type_from_file(httpd_req_t *req,
{
return httpd_resp_set_type(req, "font/woff2");
}
else if (IS_FILE_EXT(filename, ".json"))
{
return httpd_resp_set_type(req, "application/json");
}
/* This is a limited set only */
/* For any other type always set as plain text */
return httpd_resp_set_type(req, "text/plain");
@ -137,7 +141,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
}
/* Send HTML file header */
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body style=\"font-family: monospace;\"");
/* Get handle to embedded file upload script */
extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
@ -150,7 +154,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
/* Send file-list table definition and column labels */
httpd_resp_sendstr_chunk(
req,
"<table class=\"fixed\" border=\"0\">"
"<table border=\"0\">"
"<col width=\"600px\" /><col width=\"200px\" /><col width=\"200px\" /><col width=\"100px\" />"
"<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th><th>Delete</th></tr></thead>"
"<tbody>");
@ -167,8 +171,9 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
continue;
}
sprintf(entrysize, "%ld", entry_stat.st_size);
#if FILE_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
#endif
/* Send chunk of HTML file containing table entries with file name and size */
httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
httpd_resp_sendstr_chunk(req, req->uri);
@ -213,9 +218,11 @@ esp_err_t download_get_handler(httpd_req_t *req)
const char *filename = get_path_from_uri(filepath, ((struct file_server_data*) req->user_ctx)->base_path2,
req->uri,
sizeof(filepath));
#if FILE_SERVER_DEBUG_LEVEL > 0
ESP_LOGW(TAG, "FILE_GET_URI %s", req->uri);
ESP_LOGW(TAG, "FILE_GET_FILEPATH %s", filepath);
ESP_LOGW(TAG, "FILE_GET_FILENAME %s", filename);
#endif
if (!filename)
{
@ -255,8 +262,9 @@ esp_err_t download_get_handler(httpd_req_t *req)
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
return ESP_FAIL;
}
#if FILE_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
#endif
set_content_type_from_file(req, filename);
/* Retrieve the pointer to scratch buffer for temporary storage */
@ -288,8 +296,9 @@ esp_err_t download_get_handler(httpd_req_t *req)
/* Close file after sending complete */
fclose(fd);
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "File sending complete");
#endif
/* Respond with an empty chunk to signal HTTP response completion */
#ifdef CONFIG_EXAMPLE_HTTPD_CONN_CLOSE_HEADER
httpd_resp_set_hdr(req, "Connection", "close");
@ -310,10 +319,11 @@ esp_err_t upload_post_handler(httpd_req_t *req)
const char *filename = get_path_from_uri(filepath, ((struct file_server_data*) req->user_ctx)->base_path2,
req->uri + sizeof("/upload") - 1,
sizeof(filepath));
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGW(TAG, "FILE_POST_URI %s", req->uri);
ESP_LOGW(TAG, "FILE_POST_FILEPATH %s", filepath);
ESP_LOGW(TAG, "FILE_POST_FILENAME %s", filename);
#endif
if (!filename)
{
/* Respond with 500 Internal Server Error */
@ -329,13 +339,7 @@ esp_err_t upload_post_handler(httpd_req_t *req)
return ESP_FAIL;
}
if (stat(filepath, &file_stat) == 0)
{
ESP_LOGE(TAG, "File already exists : %s", filepath);
/* Respond with 400 Bad Request */
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File already exists");
return ESP_FAIL;
}
/* File cannot be larger than a limit */
if (req->content_len > MAX_FILE_SIZE)
@ -350,6 +354,16 @@ esp_err_t upload_post_handler(httpd_req_t *req)
return ESP_FAIL;
}
if (stat(filepath, &file_stat) == 0)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGW(TAG, "File already exists : %s", filepath);
#endif
unlink(filepath);
}
fd = fopen(filepath, "w");
if (!fd)
{
@ -359,8 +373,9 @@ esp_err_t upload_post_handler(httpd_req_t *req)
return ESP_FAIL;
}
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Receiving file : %s...", filename);
#endif
/* Retrieve the pointer to scratch buffer for temporary storage */
char *buf = ((struct file_server_data*) req->user_ctx)->scratch;
int received;
@ -371,8 +386,9 @@ esp_err_t upload_post_handler(httpd_req_t *req)
while (remaining > 0)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Remaining size : %d", remaining);
#endif
/* Receive the file part by part into a buffer */
if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0)
{
@ -414,8 +430,9 @@ esp_err_t upload_post_handler(httpd_req_t *req)
/* Close file upon upload completion */
fclose(fd);
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "File reception complete");
#endif
/* Redirect onto root to see the updated file list */
httpd_resp_set_status(req, "303 See Other");
httpd_resp_set_hdr(req, "Location", "/storage/");
@ -459,8 +476,9 @@ esp_err_t delete_post_handler(httpd_req_t *req)
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File does not exist");
return ESP_FAIL;
}
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Deleting file : %s", filename);
#endif
/* Delete file */
unlink(filepath);

View File

@ -16,22 +16,24 @@
* Project: ChargePointMainboard
* Created on: 2022-07-21
* Author: Bogdan Pilyugin
* Description:
* Description:
*/
#include <string.h>
#include "../include/SysConfiguration.h"
#include "NetTransport.h"
#include "driver/gpio.h"
#include "driver/uart.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"
#include "sdkconfig.h"
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
static EventGroupHandle_t event_group = NULL;
@ -41,275 +43,307 @@ 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 = { "-", "-", "-", "-" };
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; }
void PPPConnReset(void) { isPPPConn = false; }
#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)
{
ESP_LOGI(TAG, "PPP state changed event %u", (unsigned int)event_id);
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);
}
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) {
/* User interrupted event from esp-netif */
esp_netif_t *netif = event_data;
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
}
}
static void on_ip_event(void *arg, esp_event_base_t event_base,
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)
{
esp_netif_dns_info_t dns_info;
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) {
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;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
esp_netif_t *netif = event->esp_netif;
ESP_LOGI(TAG, "Modem Connect to PPP Server");
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
esp_netif_get_dns_info(netif, 0, &dns_info);
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
esp_netif_get_dns_info(netif, 1, &dns_info);
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
xEventGroupSetBits(event_group, CONNECT_BIT);
isPPPConn = true;
ESP_LOGI(TAG, "GOT ip event!!!");
}
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)
{
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));
}
#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));
#endif
ESP_LOGI(TAG, "Modem Connect to PPP Server");
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
esp_netif_get_dns_info(netif, 0, &dns_info);
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
esp_netif_get_dns_info(netif, 1, &dns_info);
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
xEventGroupSetBits(event_group, CONNECT_BIT);
isPPPConn = true;
ESP_LOGI(TAG, "GOT ip event!!!");
} 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) {
ESP_LOGI(TAG, "GOT IPv6 event!");
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
}
}
void ModemNotReady(void)
{
void ModemNotReady(void) {}
}
static void GSMInitTask(void *pvParameter) {
isPPPinitializing = true;
int starttype = *((int *)pvParameter);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event);
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID,
&on_ppp_changed);
static void GSMInitTask(void *pvParameter)
{
isPPPinitializing = true;
int starttype = *((int*) pvParameter);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event);
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed);
if (dce) {
esp_modem_destroy(dce);
}
if (dce)
{
esp_modem_destroy(dce);
}
if (ppp_netif != NULL) {
esp_netif_destroy(ppp_netif);
}
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)
{
gsm_reset(0);
vTaskDelay(pdMS_TO_TICKS(1000));
gsm_reset(1);
}
else
{
ESP_LOGE(TAG, "ethernet chip reset pin not defined");
ESP_ERROR_CHECK(1);
}
if (gsm_reset) {
gsm_reset(0);
vTaskDelay(pdMS_TO_TICKS(5000));
gsm_reset(1);
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));
event_group = xEventGroupCreate();
/* Configure the DTE */
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
dte_config.uart_config.port_num = CONFIG_MODEM_UART_PORT_NUM;
dte_config.uart_config.tx_io_num = CONFIG_MODEM_UART_TX_PIN;
dte_config.uart_config.rx_io_num = CONFIG_MODEM_UART_RX_PIN;
dte_config.uart_config.rts_io_num = CONFIG_MODEM_UART_RTS_PIN;
dte_config.uart_config.cts_io_num = CONFIG_MODEM_UART_CTS_PIN;
dte_config.uart_config.rx_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE;
dte_config.uart_config.tx_buffer_size = CONFIG_MODEM_UART_TX_BUFFER_SIZE;
dte_config.uart_config.event_queue_size = CONFIG_MODEM_UART_EVENT_QUEUE_SIZE;
dte_config.task_stack_size = CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE;
dte_config.task_priority = CONFIG_MODEM_UART_EVENT_TASK_PRIORITY;
dte_config.dte_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE / 2;
/* Configure the DCE */
esp_modem_dce_config_t dce_config =
ESP_MODEM_DCE_DEFAULT_CONFIG(GetSysConf()->gsmSettings.APN);
/* Configure the PPP netif */
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_PPP();
esp_netif_conf.route_prio = PPP_PRIO;
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
netif_ppp_config.base = &esp_netif_conf;
/* Init netif object */
ppp_netif = esp_netif_new(&netif_ppp_config);
assert(ppp_netif);
dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config,
ppp_netif);
assert(dce);
if (esp_modem_set_baud(dce, CUSTOM_MODEM_BAUDRATE) == ESP_OK)
uart_set_baudrate(CONFIG_MODEM_UART_PORT_NUM, CUSTOM_MODEM_BAUDRATE);
mod_info.model[0] = 0x00;
int OperationRepeate = 0;
// MODULE NAME
while (esp_modem_get_module_name(dce, mod_info.model) != ESP_OK) {
if (OperationRepeate++ >= MAX_COMMAND_REPEATE_NUMBER) {
ESP_LOGE(TAG, "Error get module name");
goto modem_init_fail;
}
ESP_LOGW(TAG, "Retry get module name");
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGI(TAG, "Module type:%s", mod_info.model);
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
event_group = xEventGroupCreate();
/* Configure the DTE */
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
//dte_config.uart_config.port_num = CONFIG_MODEM_UART_PORT_NUM;
dte_config.uart_config.tx_io_num = CONFIG_MODEM_UART_TX_PIN;
dte_config.uart_config.rx_io_num = CONFIG_MODEM_UART_RX_PIN;
dte_config.uart_config.rts_io_num = CONFIG_MODEM_UART_RTS_PIN;
dte_config.uart_config.cts_io_num = CONFIG_MODEM_UART_CTS_PIN;
dte_config.uart_config.rx_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE;
dte_config.uart_config.tx_buffer_size = CONFIG_MODEM_UART_TX_BUFFER_SIZE;
dte_config.uart_config.event_queue_size = CONFIG_MODEM_UART_EVENT_QUEUE_SIZE;
dte_config.task_stack_size = CONFIG_MODEM_UART_EVENT_TASK_STACK_SIZE;
dte_config.task_priority = CONFIG_MODEM_UART_EVENT_TASK_PRIORITY;
dte_config.dte_buffer_size = CONFIG_MODEM_UART_RX_BUFFER_SIZE / 2;
/* Configure the DCE */
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_MODEM_PPP_APN);
/* Configure the PPP netif */
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_PPP();
esp_netif_conf.route_prio = PPP_PRIO;
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
netif_ppp_config.base = &esp_netif_conf;
/* Init netif object */
ppp_netif = esp_netif_new(&netif_ppp_config);
assert(ppp_netif);
dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, ppp_netif);
assert(dce);
mod_info.model[0] = 0x00;
int GSMConnectTimeout = 0;
while (esp_modem_get_module_name(dce, mod_info.model) != ESP_OK)
{
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
goto modem_init_fail;
vTaskDelay(pdMS_TO_TICKS(1000));
// IMSI
OperationRepeate = 0;
mod_info.imsi[0] = 0x00;
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_LOGI(TAG, "Module type:%s", mod_info.model);
ESP_LOGW(TAG, "Retry get IMSI");
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGI(TAG, "IMSI:%s", mod_info.imsi);
mod_info.imsi[0] = 0x00;
while (esp_modem_get_imsi(dce, mod_info.imsi) != ESP_OK)
{
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
goto modem_init_fail;
vTaskDelay(pdMS_TO_TICKS(1000));
// OPERATOR NAME
OperationRepeate = 0;
mod_info.oper[0] = 0x00;
int tech = 0;
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;
}
ESP_LOGI(TAG, "IMSI:%s", mod_info.imsi);
ESP_LOGW(TAG, "Retry get operator name");
vTaskDelay(pdMS_TO_TICKS(10000));
}
ESP_LOGI(TAG, "Operator:%s", mod_info.oper);
mod_info.oper[0] = 0x00;
int tech = 0;
while (esp_modem_get_operator_name(dce, mod_info.oper, &tech) != ESP_OK)
{
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
goto modem_init_fail;
vTaskDelay(pdMS_TO_TICKS(1000));
// IMEI
mod_info.imei[0] = 0x00;
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_LOGI(TAG, "Operator:%s", mod_info.oper);
ESP_LOGW(TAG, "Retry get IMEI");
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGI(TAG, "IMEI:%s", mod_info.imei);
mod_info.imei[0] = 0x00;
while (esp_modem_get_imei(dce, mod_info.imei) != ESP_OK)
{
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
goto modem_init_fail;
vTaskDelay(pdMS_TO_TICKS(1000));
// 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_LOGI(TAG, "IMEI:%s", mod_info.imei);
ESP_LOGW(TAG, "Retry switch module to CMUX");
vTaskDelay(pdMS_TO_TICKS(1000));
}
while (esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX) != ESP_OK)
{
if (++GSMConnectTimeout >= PPP_MODEM_TIMEOUT)
goto modem_init_fail;
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_LOGI(TAG, "PPP data mode OK");
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE,
pdMS_TO_TICKS(WAIT_FOR_GET_IP * 1000));
ESP_LOGI(TAG, "PPP data mode OK");
isPPPinitializing = false;
vTaskDelete(NULL);
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
isPPPinitializing = false;
vTaskDelete(NULL);
return;
return;
modem_init_fail:
ESP_LOGE(TAG, "PPP modem init error");
isPPPinitializing = false;
vTaskDelete(NULL);
ESP_LOGE(TAG, "PPP modem initialization fail");
isPPPinitializing = false;
vTaskDelete(NULL);
}
void PPPModemColdStart(void)
{
ResetType = 0;
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
void PPPModemColdStart(void) {
ResetType = 0;
xTaskCreatePinnedToCore(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3,
&initTaskhandle, 1);
ESP_LOGI(TAG, "Start GSM cold initialization task");
}
void PPPModemSoftRestart(void)
{
ResetType = 1;
xTaskCreate(GSMInitTask, "GSMInitTask", 1024 * 6, &ResetType, 3, &initTaskhandle);
void PPPModemSoftRestart(void) {
ResetType = 1;
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");
PPPModemColdStart();
}
vTaskDelay(pdMS_TO_TICKS(30000));
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(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, 0);
}
int PPPModemGetRSSI(void)
{
int rssi = -1, ber;
int PPPModemGetRSSI(void) {
int rssi = -1, ber;
if (isPPPConn)
esp_modem_get_signal_quality(dce, &rssi, &ber);
//ESP_LOGW(TAG, "Signal %d, ber %d", rssi, ber);
return rssi;
return rssi;
}
void ModemSendAT(char *cmd, char *resp, int timeout)
{
esp_modem_at(dce, cmd, resp, timeout);
ESP_LOGI(TAG, "Command:%s", cmd);
ESP_LOGW(TAG, "%s", resp);
void ModemSetATTimeout(int timeout) { attimeout = timeout; }
void ModemSendAT(char *cmd, char *resp, int timeout) {
ESP_LOGI(TAG, "Command:%s", cmd);
int res = esp_modem_at(dce, cmd, resp, attimeout);
switch (res) {
case 0:
ESP_LOGI(TAG, "OK");
break;
case 1:
ESP_LOGE(TAG, "FAIL");
break;
case 2:
ESP_LOGE(TAG, "TIMEOUT");
break;
}
ESP_LOGI(TAG, "Response:%s", resp);
}
void ModemSendSMS(void)
{
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); }
#endif

View File

@ -42,6 +42,7 @@ HTTP_IO_RESULT HTTPPostSysAPI(httpd_req_t *req, char *PostData)
M.outputDataLength = EXPECTED_MAX_DATA_SIZE;
ServiceDataHandler(&M);
httpd_resp_set_type(req, "application/json");
httpd_resp_set_hdr(req, "Connection", "close");
httpd_resp_sendstr(req, respbuf);
free(respbuf);
return HTTP_IO_DONE_API;

View File

@ -1,657 +0,0 @@
/*! Copyright 2022 Bogdan Pilyugin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \file HTTPPostSystem.c
* \version 1.0
* \date 2022-08-14
* \author Bogdan Pilyugin
* \brief
* \details
* \copyright Apache License, Version 2.0
*/
#include "HTTPServer.h"
#include "LoRaWAN.h"
#include "Helpers.h"
#include "MQTT.h"
#include "UserCallbacks.h"
static const char *TAG = "HTTPServerPost";
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
char rtstat[2048];
const char url_adapters[] = "adapters.html";
const char url_services[] = "services.html";
const char url_system[] = "system.html";
const char url_reboot[] = "reboot.html";
const char url_api[] = "api";
static HTTP_IO_RESULT AfterPostHandler(httpd_req_t *req, const char *filename, char *PostData);
static HTTP_IO_RESULT HTTPPostAdaptersSettings(httpd_req_t *req, char *PostData);
static HTTP_IO_RESULT HTTPPostServicesSettings(httpd_req_t *req, char *PostData);
static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData);
static HTTP_IO_RESULT HTTPPostReboot(httpd_req_t *req, char *PostData);
HTTP_IO_RESULT (*AfterPostHandlerCust)(httpd_req_t *req, const char *filename, char *PostData);
void regAfterPostHandlerCustom(HTTP_IO_RESULT (*post_handler)(httpd_req_t *req, const char *filename, char *PostData))
{
AfterPostHandlerCust = post_handler;
}
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData)
{
const char *pt = filename + 1;
#if HTTP_SERVER_DEBUG_LEVEL > 0
//ESP_LOGI(TAG, "URI for POST processing:%s", req->uri);
ESP_LOGI(TAG, "Filename:%s", pt);
ESP_LOGI(TAG, "DATA for POST processing:%s", PostData);
#endif
HTTP_IO_RESULT res = AfterPostHandler(req, pt, PostData);
switch (res)
{
case HTTP_IO_DONE:
break;
case HTTP_IO_WAITING:
break;
case HTTP_IO_NEED_DATA:
break;
case HTTP_IO_REDIRECT:
strcpy((char*) filename, PostData);
break;
case HTTP_IO_DONE_NOREFRESH:
break;
case HTTP_IO_DONE_API:
break;
break;
}
return res;
}
static HTTP_IO_RESULT AfterPostHandler(httpd_req_t *req, const char *filename, char *PostData)
{
if (!memcmp(filename, url_api, sizeof(url_api)))
return HTTPPostSysAPI(req, PostData);
if (!memcmp(filename, url_adapters, sizeof(url_adapters)))
return HTTPPostAdaptersSettings(req, PostData);
if (!memcmp(filename, url_services, sizeof(url_services)))
return HTTPPostServicesSettings(req, PostData);
if (!memcmp(filename, url_system, sizeof(url_system)))
return HTTPPostSystemSettings(req, PostData);
if (!memcmp(filename, url_reboot, sizeof(url_reboot)))
return HTTPPostReboot(req, PostData);
// If not found target URL here, try to call custom code
if (AfterPostHandlerCust != NULL)
return AfterPostHandlerCust(req, filename, PostData);
return HTTP_IO_DONE;
}
static HTTP_IO_RESULT HTTPPostAdaptersSettings(httpd_req_t *req, char *PostData)
{
char tmp[33];
#if CONFIG_WEBGUIAPP_ETHERNET_ENABLE
bool TempIsETHEnabled = false;
bool TempIsETHDHCPEnabled = false;
if (httpd_query_key_value(PostData, "ethen", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsETHEnabled = true;
}
if (httpd_query_key_value(PostData, "edhcp", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsETHDHCPEnabled = true;
}
if (httpd_query_key_value(PostData, "eipa", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.IPAddr);
if (httpd_query_key_value(PostData, "emas", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Mask);
if (httpd_query_key_value(PostData, "egte", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.Gateway);
if (httpd_query_key_value(PostData, "edns1", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr1);
if (httpd_query_key_value(PostData, "edns2", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr2);
if (httpd_query_key_value(PostData, "edns3", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->ethSettings.DNSAddr3);
#endif
#if CONFIG_WEBGUIAPP_WIFI_ENABLE
bool TempIsWiFiEnabled = false;
bool TempIsWIFIDHCPEnabled = false;
if (httpd_query_key_value(PostData, "wifien", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsWiFiEnabled = true;
}
if (httpd_query_key_value(PostData, "wfmode", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "sta"))
GetSysConf()->wifiSettings.WiFiMode = WIFI_MODE_STA;
else if (!strcmp((const char*) tmp, (const char*) "ap"))
GetSysConf()->wifiSettings.WiFiMode = WIFI_MODE_AP;
else if (!strcmp((const char*) tmp, (const char*) "apsta"))
GetSysConf()->wifiSettings.WiFiMode = WIFI_MODE_APSTA;
}
if (httpd_query_key_value(PostData, "wifipwr", tmp, sizeof(tmp)) == ESP_OK)
{
uint8_t pwr = atoi((const char*) tmp);
if (pwr >= 1 && pwr <= 20)
GetSysConf()->wifiSettings.MaxPower = pwr * 4;
}
/*AP section*/
httpd_query_key_value(PostData, "wfiap", GetSysConf()->wifiSettings.ApSSID,
sizeof(GetSysConf()->wifiSettings.ApSSID));
if (httpd_query_key_value(PostData, "wfpap", tmp, sizeof(tmp)) == ESP_OK)
{
if (strcmp(tmp, (const char*) "********"))
strcpy(GetSysConf()->wifiSettings.ApSecurityKey, tmp);
}
if (httpd_query_key_value(PostData, "ipaap", tmp, sizeof(tmp)) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.ApIPAddr);
httpd_query_key_value(PostData, "wfi", GetSysConf()->wifiSettings.InfSSID,
sizeof(GetSysConf()->wifiSettings.InfSSID));
if (httpd_query_key_value(PostData, "wfp", tmp, sizeof(tmp)) == ESP_OK)
{
if (strcmp(tmp, (const char*) "********"))
strcpy(GetSysConf()->wifiSettings.InfSecurityKey, tmp);
}
/*STATION section*/
if (httpd_query_key_value(PostData, "dhcp", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsWIFIDHCPEnabled = true;
}
if (httpd_query_key_value(PostData, "ipa", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.InfIPAddr);
if (httpd_query_key_value(PostData, "mas", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.InfMask);
if (httpd_query_key_value(PostData, "gte", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.InfGateway);
if (httpd_query_key_value(PostData, "dns", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.DNSAddr1);
if (httpd_query_key_value(PostData, "dns2", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.DNSAddr2);
if (httpd_query_key_value(PostData, "dns3", tmp, 15) == ESP_OK)
esp_netif_str_to_ip4(tmp, (esp_ip4_addr_t*) &GetSysConf()->wifiSettings.DNSAddr3);
#endif
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
bool TempIsGSMEnabled = false;
if (httpd_query_key_value(PostData, "gsmen", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsGSMEnabled = true;
}
if (httpd_query_key_value(PostData, "sav", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
GetSysConf()->gsmSettings.Flags1.bIsGSMEnabled = TempIsGSMEnabled;
WriteNVSSysConfig(GetSysConf());
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
if (httpd_query_key_value(PostData, "restart", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
//PPPModemSoftRestart();
}
}
if (httpd_query_key_value(PostData, "hdrst", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
//PPPModemColdStart();
}
}
#endif
#if CONFIG_WEBGUIAPP_LORAWAN_ENABLE
bool TempIsLoRaEnabled = false;
if (httpd_query_key_value(PostData, "lren", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsLoRaEnabled = true;
}
if (httpd_query_key_value(PostData, "lrdvid", tmp, sizeof(tmp)) == ESP_OK)
{
if (strlen(tmp) == 16)
StrToBytesLen((unsigned char*) tmp, (unsigned char*) GetSysConf()->lorawanSettings.DevEui, 16);
}
if (httpd_query_key_value(PostData, "lrapid", tmp, sizeof(tmp)) == ESP_OK)
{
if (strlen(tmp) == 16)
StrToBytesLen((unsigned char*) tmp, (unsigned char*) GetSysConf()->lorawanSettings.AppEui, 16);
}
if (httpd_query_key_value(PostData, "lrapkey", tmp, sizeof(tmp)) == ESP_OK)
{
if (strlen(tmp) == 32)
StrToBytesLen((unsigned char*) tmp, (unsigned char*) GetSysConf()->lorawanSettings.AppKey, 32);
}
#endif
if (httpd_query_key_value(PostData, "wifisc", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
WiFiScan();
}
}
if (httpd_query_key_value(PostData, "wifistart", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
WiFiStartAPTemp(120);
}
}
if (httpd_query_key_value(PostData, "wifistop", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
WiFiStopAP();
}
}
if (httpd_query_key_value(PostData, "wifisave", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
WriteNVSSysConfig(GetSysConf());
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
if (httpd_query_key_value(PostData, "save", tmp, 5) == ESP_OK ||
httpd_query_key_value(PostData, "apply", tmp, 5) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "eth"))
{
#if CONFIG_WEBGUIAPP_ETHERNET_ENABLE
GetSysConf()->ethSettings.Flags1.bIsETHEnabled = TempIsETHEnabled;
GetSysConf()->ethSettings.Flags1.bIsDHCPEnabled = TempIsETHDHCPEnabled;
#endif
}
else if (!strcmp(tmp, (const char*) "wifi"))
{
#if CONFIG_WEBGUIAPP_WIFI_ENABLE
GetSysConf()->wifiSettings.Flags1.bIsWiFiEnabled = TempIsWiFiEnabled;
GetSysConf()->wifiSettings.Flags1.bIsDHCPEnabled = TempIsWIFIDHCPEnabled;
#endif
}
else if (!strcmp(tmp, (const char*) "gprs"))
{
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
GetSysConf()->gsmSettings.Flags1.bIsGSMEnabled = TempIsGSMEnabled;
#endif
}
else if (!strcmp(tmp, (const char*) "lora"))
{
#if CONFIG_WEBGUIAPP_LORAWAN_ENABLE
GetSysConf()->lorawanSettings.Flags1.bIsLoRaWANEnabled = TempIsLoRaEnabled;
#endif
}
if (httpd_query_key_value(PostData, "apply", tmp, 5) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
return HTTP_IO_DONE;
}
else if (httpd_query_key_value(PostData, "save", tmp, 5) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
return HTTP_IO_DONE;
}
static HTTP_IO_RESULT HTTPPostServicesSettings(httpd_req_t *req, char *PostData)
{
char tmp[64];
#if CONFIG_WEBGUIAPP_MQTT_ENABLE
bool TempIsMQTT1Enabled = false;
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
bool TempIsMQTT2Enabled = false;
#endif
httpd_query_key_value(PostData, "mqurl1", GetSysConf()->mqttStation[0].ServerAddr,
sizeof(GetSysConf()->mqttStation[0].ServerAddr));
httpd_query_key_value(PostData, "mqid1", GetSysConf()->mqttStation[0].ClientID,
sizeof(GetSysConf()->mqttStation[0].ClientID));
httpd_query_key_value(PostData, "mqsys1", GetSysConf()->mqttStation[0].SystemName,
sizeof(GetSysConf()->mqttStation[0].SystemName));
httpd_query_key_value(PostData, "mqgrp1", GetSysConf()->mqttStation[0].GroupName,
sizeof(GetSysConf()->mqttStation[0].GroupName));
httpd_query_key_value(PostData, "mqname1", GetSysConf()->mqttStation[0].UserName,
sizeof(GetSysConf()->mqttStation[0].UserName));
if (httpd_query_key_value(PostData, "mqen1", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsMQTT1Enabled = true;
}
if (httpd_query_key_value(PostData, "mqport1", tmp, sizeof(tmp)) == ESP_OK)
{
uint16_t tp = atoi((const char*) tmp);
if (tp < 65535 && tp >= 1000)
GetSysConf()->mqttStation[0].ServerPort = tp;
}
if (httpd_query_key_value(PostData, "mqpass1", tmp, sizeof(tmp)) == ESP_OK &&
strcmp(tmp, (const char*) "******"))
{
strcpy(GetSysConf()->mqttStation[0].UserPass, tmp);
}
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
httpd_query_key_value(PostData, "mqurl2", GetSysConf()->mqttStation[1].ServerAddr,
sizeof(GetSysConf()->mqttStation[1].ServerAddr));
httpd_query_key_value(PostData, "mqid2", GetSysConf()->mqttStation[1].ClientID,
sizeof(GetSysConf()->mqttStation[1].ClientID));
httpd_query_key_value(PostData, "mqsys2", GetSysConf()->mqttStation[1].SystemName,
sizeof(GetSysConf()->mqttStation[1].SystemName));
httpd_query_key_value(PostData, "mqgrp2", GetSysConf()->mqttStation[1].GroupName,
sizeof(GetSysConf()->mqttStation[1].GroupName));
httpd_query_key_value(PostData, "mqname2", GetSysConf()->mqttStation[1].UserName,
sizeof(GetSysConf()->mqttStation[1].UserName));
if (httpd_query_key_value(PostData, "mqen2", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsMQTT2Enabled = true;
}
if (httpd_query_key_value(PostData, "mqport2", tmp, sizeof(tmp)) == ESP_OK)
{
uint16_t tp = atoi((const char*) tmp);
if (tp < 65535 && tp >= 1000)
GetSysConf()->mqttStation[1].ServerPort = tp;
}
if (httpd_query_key_value(PostData, "mqpass2", tmp, sizeof(tmp)) == ESP_OK &&
strcmp(tmp, (const char*) "******"))
{
strcpy(GetSysConf()->mqttStation[1].UserPass, tmp);
}
#endif
/*SNTP*/
bool TempIsSNTPEnabled = false;
if (httpd_query_key_value(PostData, "sntpen", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsSNTPEnabled = true;
}
httpd_query_key_value(PostData, "tsr", GetSysConf()->sntpClient.SntpServerAdr,
sizeof(GetSysConf()->sntpClient.SntpServerAdr));
httpd_query_key_value(PostData, "tsr2", GetSysConf()->sntpClient.SntpServer2Adr,
sizeof(GetSysConf()->sntpClient.SntpServer2Adr));
httpd_query_key_value(PostData, "tsr3", GetSysConf()->sntpClient.SntpServer3Adr,
sizeof(GetSysConf()->sntpClient.SntpServer3Adr));
/*MQTT Test button handlers*/
if (httpd_query_key_value(PostData, "mqtttest1", tmp, 6) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
if (GetSysConf()->mqttStation[0].Flags1.bIsGlobalEnabled)
PublicTestMQTT(0);
return HTTP_IO_DONE;
}
}
if (httpd_query_key_value(PostData, "mqtttest2", tmp, 6) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
if (GetSysConf()->mqttStation[1].Flags1.bIsGlobalEnabled)
PublicTestMQTT(1);
return HTTP_IO_DONE;
}
}
if (httpd_query_key_value(PostData, "save", tmp, 6) == ESP_OK ||
httpd_query_key_value(PostData, "apply", tmp, 6) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "mqtt1"))
{
GetSysConf()->mqttStation[0].Flags1.bIsGlobalEnabled = TempIsMQTT1Enabled;
}
else if (!strcmp(tmp, (const char*) "mqtt2"))
{
#if CONFIG_WEBGUIAPP_MQTT_CLIENTS_NUM == 2
GetSysConf()->mqttStation[1].Flags1.bIsGlobalEnabled = TempIsMQTT2Enabled;
#endif
}
else if (!strcmp(tmp, (const char*) "sntp"))
{
GetSysConf()->sntpClient.Flags1.bIsGlobalEnabled = TempIsSNTPEnabled;
}
if (httpd_query_key_value(PostData, "apply", tmp, 6) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
return HTTP_IO_DONE;
}
else if (httpd_query_key_value(PostData, "save", tmp, 6) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
#endif
return HTTP_IO_DONE;
}
static HTTP_IO_RESULT HTTPPostSystemSettings(httpd_req_t *req, char *PostData)
{
char tmp[128];
bool TempIsOTAEnabled = false;
bool TempIsRstEnabled = false;
if (httpd_query_key_value(PostData, "nam", tmp, sizeof(tmp)) == ESP_OK)
{
UnencodeURL(tmp);
strcpy(GetSysConf()->NetBIOSName, tmp);
}
httpd_query_key_value(PostData, "lgn", GetSysConf()->SysName, sizeof(GetSysConf()->SysName));
if (httpd_query_key_value(PostData, "psn", tmp, sizeof(tmp)) == ESP_OK)
{
if (strcmp(tmp, (const char*) "******"))
strcpy(GetSysConf()->SysPass, tmp);
}
if (httpd_query_key_value(PostData, "ota", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsOTAEnabled = true;
}
if (httpd_query_key_value(PostData, "otarst", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp((const char*) tmp, (const char*) "1"))
TempIsRstEnabled = true;
}
if (httpd_query_key_value(PostData, "otaint", tmp, sizeof(tmp)) == ESP_OK)
{
uint16_t tp = atoi((const char*) tmp);
if (tp < 65535 && tp >= 1)
GetSysConf()->OTAAutoInt = tp;
}
if (httpd_query_key_value(PostData, "otaurl", tmp, sizeof(tmp)) == ESP_OK)
{
UnencodeURL(tmp);
strcpy(GetSysConf()->OTAURL, tmp);
}
if (httpd_query_key_value(PostData, "colscheme", tmp, sizeof(tmp)) == ESP_OK)
{
uint16_t chm = atoi((const char*) tmp);
if (chm < 3 && chm >= 1)
GetSysConf()->ColorSheme = chm;
}
if (httpd_query_key_value(PostData, "upd", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
StartOTA(true);
}
}
if (httpd_query_key_value(PostData, "rtos", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
#if (CONFIG_FREERTOS_USE_TRACE_FACILITY == 1)
vTaskGetRunTimeStatsCustom(rtstat);
httpd_resp_sendstr(req, rtstat);
#endif
return HTTP_IO_DONE_API;
}
}
if (httpd_query_key_value(PostData, "rst", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
if (httpd_query_key_value(PostData, "save", tmp, sizeof(tmp)) == ESP_OK ||
httpd_query_key_value(PostData, "apply", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "syst"))
{
GetSysConf()->Flags1.bIsOTAEnabled = TempIsOTAEnabled;
GetSysConf()->Flags1.bIsResetOTAEnabled = TempIsRstEnabled;
}
if (httpd_query_key_value(PostData, "apply", tmp, 5) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
return HTTP_IO_DONE;
}
else if (httpd_query_key_value(PostData, "save", tmp, 5) == ESP_OK)
{
WriteNVSSysConfig(GetSysConf());
memcpy(PostData, "/reboot.html", sizeof "/reboot.html");
return HTTP_IO_REDIRECT;
}
}
if (httpd_query_key_value(PostData, "cmd", tmp, 4) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "1"))
{
return HTTP_IO_DONE_NOREFRESH;
}
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
else if (!strcmp(tmp, (const char*) "2"))
{
char resp[256] = {0};
ModemSendAT("AT+CCLK?\r", resp, 200);
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "3"))
{
char resp[256] = {0};
ModemSendAT("ATD+79022518532;\r", resp, 200);
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "4"))
{
char resp[256] = {0};
ModemSendAT("ATH\r", resp, 200);
return HTTP_IO_DONE_NOREFRESH;
}
#endif
else if (!strcmp(tmp, (const char*) "5"))
{
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "6"))
{
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "7"))
{
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "8"))
{
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "9"))
{
return HTTP_IO_DONE_NOREFRESH;
}
else if (!strcmp(tmp, (const char*) "10"))
{
GenerateSystemSettingsJSONFile();
return HTTP_IO_DONE_NOREFRESH;
}
}
return HTTP_IO_DONE;
}
static HTTP_IO_RESULT HTTPPostReboot(httpd_req_t *req, char *PostData)
{
char tmp[33];
if (httpd_query_key_value(PostData, "rbt", tmp, sizeof(tmp)) == ESP_OK)
{
if (!strcmp(tmp, (const char*) "prs"))
{
DelayedRestart();
}
}
return HTTP_IO_DONE;
}

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@ struct file_server_data *server_data = NULL;
httpd_handle_t server = NULL;
static const char *TAG = "HTTPServer";
const char url_api[] = "/api";
//Pointer to external user defined rest api handler
static int (*HTTPUserRestAPI)(char *url, char *req, int len, char *resp) = NULL;
void regHTTPUserRestAPI(int (*api_handler)(char *url, char *req, int len, char *resp))
@ -42,19 +43,38 @@ void regHTTPUserRestAPI(int (*api_handler)(char *url, char *req, int len, char *
HTTPUserRestAPI = api_handler;
}
char *userappurl = NULL;
static esp_err_t (*HTTPUserAppGETHandler)(httpd_req_t *req) = NULL;
static esp_err_t (*HTTPUserAppPOSTHandler)(httpd_req_t *req) = NULL;
void regHTTPUserAppHandlers(char *url,
esp_err_t (*get)(httpd_req_t *req),
esp_err_t (*post)(httpd_req_t *req))
{
userappurl = url;
HTTPUserAppGETHandler = get;
HTTPUserAppPOSTHandler = post;
}
#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)
{
@ -132,6 +152,10 @@ static esp_err_t set_content_type_from_file(httpd_req_t *req,
{
return httpd_resp_set_type(req, "font/woff2");
}
else if (IS_FILE_EXT(filename, ".json"))
{
return httpd_resp_set_type(req, "application/json");
}
/* This is a limited set only */
/* For any other type always set as plain text */
return httpd_resp_set_type(req, "text/plain");
@ -174,27 +198,33 @@ static const char* get_path_from_uri(char *dest, const char *base_path,
static esp_err_t POSTHandler(httpd_req_t *req)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "POST request handle");
ESP_LOGI(TAG, "POST request handle URL: %s", req->uri);
#endif
if(userappurl && HTTPUserAppPOSTHandler)
{
if (memmem(req->uri, strlen(req->uri), userappurl, strlen(userappurl)))
return HTTPUserAppPOSTHandler(req);
}
if (memmem(req->uri, strlen(req->uri), "/storage/upload/", sizeof("/storage/upload/") - 1))
return upload_post_handler(req);
if (memmem(req->uri, strlen(req->uri), "/storage/delete/", sizeof("/storage/delete/") - 1))
return delete_post_handler(req);
char *buf = ((struct file_server_data*) req->user_ctx)->scratch;
int received;
int offset = 0;
int remaining = req->content_len;
buf[req->content_len] = 0x00;
HTTP_IO_RESULT http_res;
while (remaining > 0)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Remaining size : %d", remaining);
#endif
/* Receive the file part by part into a buffer */
if ((received = httpd_req_recv(req, buf,
if ((received = httpd_req_recv(req, buf + offset,
MIN(remaining, SCRATCH_BUFSIZE))) <= 0)
{
if (received == HTTPD_SOCK_ERR_TIMEOUT)
@ -213,43 +243,11 @@ static esp_err_t POSTHandler(httpd_req_t *req)
/* Write buffer content to file on storage */
if (received)
offset += received;
{
char filepath[FILE_PATH_MAX];
const char *filename;
filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path,
req->uri,
sizeof(filepath));
http_res = HTTPPostApp(req, filename, buf);
if (http_res == HTTP_IO_DONE)
return GETHandler(req);
else if (http_res == HTTP_IO_REDIRECT)
{
httpd_resp_set_status(req, "307 Temporary Redirect");
httpd_resp_set_hdr(req, "Location", filename);
httpd_resp_send(req, NULL, 0); // Response body can be empty
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Redirect request from POST");
ESP_LOGI(TAG, "Received : %d", received);
#endif
return ESP_OK;
}
else if (http_res == HTTP_IO_DONE_NOREFRESH)
{
httpd_resp_set_status(req, HTTPD_204);
httpd_resp_send(req, NULL, 0); // Response body can be empty
return ESP_OK;
}
else if (http_res == HTTP_IO_DONE_API)
{
httpd_resp_send(req, NULL, 0); // Response body can be empty
return ESP_OK;
}
}
/* Keep track of remaining size of
@ -257,15 +255,40 @@ static esp_err_t POSTHandler(httpd_req_t *req)
remaining -= received;
}
char filepath[FILE_PATH_MAX];
const char *filename;
if (CheckAuth(req) != ESP_OK)
return ESP_FAIL;
filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path,
req->uri,
sizeof(filepath));
if (!memcmp(filename, url_api, sizeof(url_api)))
HTTPPostSysAPI(req, buf);
else
{
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "URL not found");
return ESP_FAIL;
}
return ESP_OK;
}
static esp_err_t GETHandler(httpd_req_t *req)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "GET request handle");
ESP_LOGI(TAG, "GET request handle URL: %s", req->uri);
#endif
if(userappurl && HTTPUserAppGETHandler)
{
if (memmem(req->uri, strlen(req->uri), userappurl, strlen(userappurl)))
return HTTPUserAppGETHandler(req);
}
//Route to file server GET handler
if (memmem(req->uri, strlen(req->uri), "/storage/", sizeof("/storage/") - 1))
return download_get_handler(req);
@ -273,9 +296,6 @@ static esp_err_t GETHandler(httpd_req_t *req)
char filepath[FILE_PATH_MAX];
espfs_file_t *file;
struct espfs_stat_t stat;
uint32_t bufSize; //size of ram buffer for chunk of data, read from file
uint32_t readBytes; //number of bytes, read from file. used for information only
const char *filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path,
req->uri,
@ -301,136 +321,83 @@ static esp_err_t GETHandler(httpd_req_t *req)
return ESP_OK;
}
//check auth for all files except status.json
if (strcmp(filename, "/status.json"))
//check auth for all files
if (CheckAuth(req) != ESP_OK)
{
if (CheckAuth(req) != ESP_OK)
{
return ESP_FAIL;
}
return ESP_FAIL;
}
//open file
file = espfs_fopen(fs, filepath);
if (!file)
{
strcat(filepath, ".gz"); //check if requested file in gzip archive
file = espfs_fopen(fs, filepath);
if (!file)
{
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
return ESP_FAIL;
}
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
return ESP_FAIL;
}
//get file info
espfs_stat(fs, filepath, &stat);
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Sending file : %s (%d bytes)...", filename,
ESP_LOGI(TAG, "BEGIN send file : %s (%d bytes)...", filename,
stat.size);
#endif
//OutputDisplay((char*) filepath);
set_content_type_from_file(req, filename);
/* Retrieve the pointer to scratch buffer for temporary storage */
char *chunk = ((struct file_server_data*) req->user_ctx)->scratch;
httpd_resp_set_hdr(req, "Cache-Control", "max-age=600");
httpd_resp_set_hdr(req, "Connection", "close");
bufSize = MIN(stat.size, SCRATCH_BUFSIZE - MAX_DYNVAR_LENGTH);
readBytes = 0;
//allocate buffer for file data
if (bufSize == 0)
bufSize = 1;
char *buf = (char*) malloc(bufSize);
if (!buf)
{
ESP_LOGE(TAG, "Failed to allocate memory");
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Out of memory");
espfs_fclose(file);
return ESP_FAIL;
}
//read first portion of data from file
readBytes = espfs_fread(file, buf, bufSize);
//check if file is compressed by GZIP and add correspondent header
if (memmem(buf, 3, GZIP_SIGN, 3))
/*Check if content of file is compressed*/
char file_header[3];
espfs_fread(file, file_header, 3);
if (!memcmp(file_header, GZIP_SIGN, 3))
{
httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
}
espfs_fseek(file, 0, SEEK_SET); //return to begin of file
httpd_resp_set_hdr(req, "Cache-Control", "max-age=600");
/* Retrieve the pointer to scratch buffer for temporary storage */
char *chunk = ((struct file_server_data*) req->user_ctx)->scratch;
size_t chunksize;
do
{
int pt = 0;
int preparedBytes = 0;
while (pt < bufSize)
/* Read file in chunks into the scratch buffer */
chunksize = espfs_fread(file, chunk, SCRATCH_BUFSIZE);
if (chunksize > 0)
{
chunk[preparedBytes++] = buf[pt++]; //write to chunk ordinary character
//check if scratch buffer is full and need send chunk
if (preparedBytes >= (SCRATCH_BUFSIZE - MAX_DYNVAR_LENGTH))
/* Send the buffer contents as HTTP response chunk */
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Call resp_send_chank because of chunk full. Send %d bytes", preparedBytes);
#endif
esp_err_t send_err = httpd_resp_send_chunk(req, chunk, preparedBytes);
if (send_err != ESP_OK)
{
ESP_LOGE(TAG, "%s", esp_err_to_name(send_err));
goto file_send_error;
}
preparedBytes = 0;
espfs_fclose(file);
ESP_LOGE(TAG, "File sending failed!");
/* Abort sending file */
httpd_resp_sendstr_chunk(req, NULL);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
return ESP_FAIL;
}
}
//data in buffer is finished and not void, need send chunk
if (preparedBytes)
{
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "Call resp_send_chank because of buf empty. Send %d bytes", preparedBytes);
#endif
if (httpd_resp_send_chunk(req, chunk, preparedBytes) != ESP_OK)
goto file_send_error;
}
//try to read next part of data from file
bufSize = espfs_fread(file, buf, bufSize);
readBytes += bufSize;
/* Keep looping till the whole file is sent */
}
while (bufSize > 0);
while (chunksize != 0);
/* Close file after sending complete */
espfs_fclose(file);
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "File sending complete, read from file %d", (int )readBytes);
ESP_LOGI(TAG, "END send file : %s (%d bytes)...", filename,
stat.size);
#endif
/* Respond with an empty chunk to signal HTTP response completion */
#ifdef CONFIG_EXAMPLE_HTTPD_CONN_CLOSE_HEADER
httpd_resp_set_hdr(req, "Connection", "close");
#endif
httpd_resp_send_chunk(req, NULL, 0);
free(buf);
espfs_fclose(file);
return ESP_OK;
file_send_error:
ESP_LOGE(TAG, "File sending failed!");
/* Abort sending file */
httpd_resp_sendstr_chunk(req, NULL);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR,
"Failed to send file");
free(buf);
espfs_fclose(file);
return ESP_FAIL;
}
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;
config.lru_purge_enable = false;
config.uri_match_fn = httpd_uri_match_wildcard;
config.max_open_sockets = 5;
config.max_resp_headers = 6;
config.max_uri_handlers = 6;
config.stack_size = (4096 + 2048);
// Start the httpd server
@ -498,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;
}

View File

@ -20,24 +20,26 @@
*/
#include <SysConfiguration.h>
#include <SystemApplication.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "Helpers.h"
#include "NetTransport.h"
#include "MQTT.h"
#include "UserCallbacks.h"
#if (ESP_IDF_VERSION_MAJOR == 5 && ESP_IDF_VERSION_MINOR > 1)
#include "esp_log_level.h"
#endif
#define TAG "MQTT"
#define SERVICE_NAME "SYSTEM" // Dedicated service name
#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 5 //size of mqtt queue
#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
@ -106,8 +108,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, "/");
@ -122,10 +124,11 @@ esp_err_t SysServiceMQTTSend(char *data, int len, int idx)
if (buf)
{
memcpy(buf, data, len);
MQTT_DATA_SEND_STRUCT DSS;
MQTT_DATA_SEND_STRUCT DSS = { 0 };
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
@ -138,7 +141,7 @@ esp_err_t SysServiceMQTTSend(char *data, int len, int idx)
return ESP_ERR_NO_MEM;
}
esp_err_t ExternalServiceMQTTSend(char *data, int len, int idx)
esp_err_t ExternalServiceMQTTSend(char *servname, char *data, int len, int idx)
{
if (GetMQTTHandlesPool(idx)->mqtt_queue == NULL)
return ESP_ERR_NOT_FOUND;
@ -146,8 +149,8 @@ esp_err_t ExternalServiceMQTTSend(char *data, int len, int idx)
if (buf)
{
memcpy(buf, data, len);
MQTT_DATA_SEND_STRUCT DSS;
ComposeTopic(DSS.topic, idx, EXTERNAL_SERVICE_NAME, UPLINK_SUBTOPIC);
MQTT_DATA_SEND_STRUCT DSS = { 0 };
ComposeTopic(DSS.topic, idx, servname, UPLINK_SUBTOPIC);
DSS.raw_data_ptr = buf;
DSS.data_length = len;
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(0)) == pdPASS)
@ -163,17 +166,79 @@ esp_err_t ExternalServiceMQTTSend(char *data, int len, int idx)
}
#define MAX_ERROR_JSON 256
#define MAX_MQTT_PUBLICTEST_MESSAGE 1024
mqtt_app_err_t PublicTestMQTT(int idx)
{
char tmp[10];
char resp[256];
char JSONMess[512];
char *data = (char*) malloc(MAX_MQTT_PUBLICTEST_MESSAGE);
if (data == NULL)
return ESP_ERR_NO_MEM;
static char resp[256];
struct jWriteControl jwc;
jwOpen(&jwc, JSONMess, MAX_ERROR_JSON, JW_OBJECT, JW_PRETTY);
jwOpen(&jwc, data, 1024 - 64, JW_OBJECT, JW_COMPACT);
jwObj_object(&jwc, "data");
time_t now;
time(&now);
jwObj_int(&jwc, "time", (unsigned int) now);
jwObj_string(&jwc, "event", "MQTT_TEST_MESSAGE)");
jwObj_int(&jwc, "msgid", (unsigned int) now);
jwObj_string(&jwc, "srcid", GetSysConf()->ID);
jwObj_string(&jwc, "dstid", "FFFFFFFF");
char time[ISO8601_TIMESTAMP_LENGTH];
GetISO8601Time(time);
jwObj_string(&jwc, "time", time);
jwObj_int(&jwc, "msgtype", DATA_MESSAGE_TYPE_COMMAND);
jwObj_int(&jwc, "payloadtype", 1000);
jwObj_object(&jwc, "payload");
jwObj_int(&jwc, "applytype", 0);
jwObj_object(&jwc, "variables");
rest_var_types tp = VAR_STRING;
GetConfVar("dev_id", resp, &tp);
jwObj_string(&jwc, "dev_id", resp);
GetConfVar("ser_num", resp, &tp);
jwObj_string(&jwc, "ser_num", resp);
GetConfVar("model_name", resp, &tp);
jwObj_string(&jwc, "model_name", resp);
GetConfVar("hw_rev", resp, &tp);
jwObj_string(&jwc, "hw_rev", resp);
tp = VAR_FUNCT;
GetConfVar("time", resp, &tp);
jwObj_raw(&jwc, "time", resp);
GetConfVar("lat", resp, &tp);
jwObj_raw(&jwc, "lat", resp);
GetConfVar("lon", resp, &tp);
jwObj_raw(&jwc, "lon", resp);
GetConfVar("uptime", resp, &tp);
jwObj_raw(&jwc, "uptime", resp);
GetConfVar("free_ram", resp, &tp);
jwObj_raw(&jwc, "free_ram", resp);
GetConfVar("free_ram_min", resp, &tp);
jwObj_raw(&jwc, "free_ram_min", resp);
GetConfVar("def_interface", resp, &tp);
jwObj_raw(&jwc, "def_interface", resp);
GetConfVar("fw_rev", resp, &tp);
jwObj_raw(&jwc, "fw_rev", resp);
GetConfVar("idf_rev", resp, &tp);
jwObj_raw(&jwc, "idf_rev", resp);
#if CONFIG_WEBGUIAPP_WIFI_ENABLE
GetConfVar("wifi_stat", resp, &tp);
jwObj_raw(&jwc, "wifi_stat", resp);
GetConfVar("wifi_level", resp, &tp);
jwObj_raw(&jwc, "wifi_level", resp);
tp = VAR_INT;
GetConfVar("wifi_mode", resp, &tp);
jwObj_raw(&jwc, "wifi_mode", resp);
tp = VAR_STRING;
GetConfVar("wifi_ap_ssid", resp, &tp);
jwObj_string(&jwc, "wifi_ap_ssid", resp);
GetConfVar("wifi_sta_ssid", resp, &tp);
jwObj_string(&jwc, "wifi_sta_ssid", resp);
#endif
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
#endif
strcpy(resp, "mqtt://");
strcat(resp, GetSysConf()->mqttStation[idx].ServerAddr);
itoa(GetSysConf()->mqttStation[idx].ServerPort, tmp, 10);
@ -184,11 +249,34 @@ mqtt_app_err_t PublicTestMQTT(int idx)
jwObj_string(&jwc, "tx_topic", resp);
ComposeTopic(resp, idx, SERVICE_NAME, DOWNLINK_SUBTOPIC);
jwObj_string(&jwc, "rx_topic", resp);
jwEnd(&jwc);
jwEnd(&jwc); //close variables
jwEnd(&jwc); //close payload
jwEnd(&jwc); //close data
//calculate sha from 'data' object
char *datap = strstr(data, "\"data\":");
if (datap)
{
datap += sizeof("\"data\":") - 1;
unsigned char sha[32 + 1];
unsigned char sha_print[32 * 2 + 1];
SHA256hmacHash((unsigned char*) datap, strlen(datap), (unsigned char*) "mykey", sizeof("mykey"), sha);
BytesToStr(sha, sha_print, 32);
sha_print[32 * 2] = 0x00;
#if REAST_API_DEBUG_MODE
ESP_LOGI(TAG, "SHA256 of DATA object is %s", sha_print);
#endif
jwObj_string(&jwc, "signature", (char*) sha_print);
}
else{
free(data);
return ESP_ERR_NOT_FOUND;}
jwClose(&jwc);
mqtt_app_err_t merr = API_OK;
if (SysServiceMQTTSend(JSONMess, strlen(JSONMess), idx) != ESP_OK)
if (SysServiceMQTTSend(data, strlen(data), idx) != ESP_OK)
merr = API_INTERNAL_ERR;
free(data);
return merr;
}
@ -214,17 +302,18 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED client %d", idx);
#endif
ComposeTopic(topic, idx, SERVICE_NAME, DOWNLINK_SUBTOPIC);
msg_id = esp_mqtt_client_subscribe(client, (const char*) topic, 0);
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, "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)
{
ComposeTopic(topic, idx, EXTERNAL_SERVICE_NAME, DOWNLINK_SUBTOPIC);
//Subscribe to the service called "APP"
msg_id = esp_mqtt_client_subscribe(client, (const char*) topic, 0);
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);
@ -239,8 +328,14 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
#endif
if (++MQTTReconnectCounter > MQTT_RECONNECT_CHANGE_ADAPTER)
{
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
char interface[3];
GetDefaultNetIFName(interface);
if(!strcmp((const char*)interface , "pp")) //Cold reboot modem on can't connect to ppp
PPPConnReset();
#endif
MQTTReconnectCounter = 0;
NextDefaultNetIF();
NextDefaultNetIF();
}
mqtt[idx].is_connected = false;
break;
@ -264,8 +359,12 @@ 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;
//Check if topic is SYSTEM and pass data to handler
ComposeTopic(topic, idx, SERVICE_NAME, DOWNLINK_SUBTOPIC);
if (!memcmp(topic, event->topic, event->topic_len))
@ -289,8 +388,8 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
}
else
ESP_LOGE(TAG, "Out of free RAM for MQTT API handle");
}
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
if (GetSysConf()->serialSettings.Flags.IsBridgeEnabled)
{
@ -319,6 +418,7 @@ static void mqtt_system_event_handler(int idx, void *handler_args, esp_event_bas
#endif
break;
}
end_of_system_handler:
xSemaphoreGive(xSemaphoreMQTTHandle);
}
@ -381,12 +481,13 @@ void MQTTTaskTransmit(void *pvParameter)
while (1)
{
while (!mqtt[idx].is_connected)
vTaskDelay(pdMS_TO_TICKS(1000));
vTaskDelay(pdMS_TO_TICKS(300));
xQueueReceive(mqtt[idx].mqtt_queue, &DSS, portMAX_DELAY);
if (mqtt[idx].mqtt)
if (mqtt[idx].mqtt && mqtt[idx].is_connected)
{
#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,
@ -394,9 +495,10 @@ void MQTTTaskTransmit(void *pvParameter)
DSS.data_length,
0, 0);
}
else
ESP_LOGE(TAG, "MQTT client not initialized");
free(DSS.raw_data_ptr);
if (!DSS.keep_memory_onfinish)
{
free(DSS.raw_data_ptr);
}
}
}
@ -428,8 +530,8 @@ static void start_mqtt()
mqtt_cfg.password = GetSysConf()->mqttStation[i].UserPass;
#endif
strcpy(tmp, GetSysConf()->mqttStation[i].ClientID);
strcat(tmp, "-");
strcat(tmp, GetSysConf()->ID);
//strcat(tmp, "-");
//strcat(tmp, GetSysConf()->ID);
#if ESP_IDF_VERSION_MAJOR >= 5
mqtt_cfg.credentials.client_id = tmp;
mqtt_cfg.network.reconnect_timeout_ms = MQTT_RECONNECT_TIMEOUT * 1000;
@ -446,7 +548,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);
}
}
}
@ -504,13 +606,19 @@ static void mqtt2_user_event_handler(void *handler_args, esp_event_base_t base,
#define MAX_MQTT_LOG_MESSAGE (1024)
#define SPIRAL_LOG_TAG "SystemExtendedLog"
char data[MAX_MQTT_LOG_MESSAGE];
//char data[MAX_MQTT_LOG_MESSAGE];
esp_err_t ExtendedLog(esp_log_level_t level, char *format, ...)
{
va_list arg;
va_start(arg, format);
va_end(arg);
char *data = (char*) malloc(MAX_MQTT_LOG_MESSAGE);
if (data == NULL)
return ESP_ERR_NO_MEM;
vsnprintf(data, MAX_MQTT_LOG_MESSAGE, format, arg);
if (strlen(data) == MAX_MQTT_LOG_MESSAGE - 1)
for (int i = 0; i < 3; i++)
*(data + MAX_MQTT_LOG_MESSAGE - 2 - i) = '.';
switch (level)
{
case ESP_LOG_INFO:
@ -525,30 +633,36 @@ esp_err_t ExtendedLog(esp_log_level_t level, char *format, ...)
case ESP_LOG_ERROR:
ESP_LOGE(SPIRAL_LOG_TAG, "%s", data);
break;
#if (ESP_IDF_VERSION_MAJOR == 5 && ESP_IDF_VERSION_MINOR > 1)
case ESP_LOG_MAX:
#endif
}
for (int idx = 0; idx < 2; idx++)
{
if (GetMQTTHandlesPool(idx)->mqtt_queue == NULL)
continue;
char time[RFC3339_TIMESTAMP_LENGTH];
GetRFC3339Time(time);
char *buf = (char*) malloc(strlen(data) + RFC3339_TIMESTAMP_LENGTH + 2);
char time[ISO8601_TIMESTAMP_LENGTH];
GetISO8601Time(time);
char *buf = (char*) malloc(strlen(data) + ISO8601_TIMESTAMP_LENGTH + 2);
if (buf)
{
strcpy(buf, time);
strcat(buf, " ");
strcat(buf, data);
MQTT_DATA_SEND_STRUCT DSS;
MQTT_DATA_SEND_STRUCT DSS = { 0 };
ComposeTopic(DSS.topic, idx, "LOG", "UPLINK");
DSS.raw_data_ptr = buf;
DSS.data_length = strlen(buf);
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(1000)) != pdPASS)
DSS.keep_memory_onfinish = false;
if (xQueueSend(GetMQTTHandlesPool(idx)->mqtt_queue, &DSS, pdMS_TO_TICKS(0)) != pdPASS)
free(buf);
continue;
}
free(data);
return ESP_ERR_NO_MEM;
}
free(data);
return ESP_OK;
}

View File

@ -30,7 +30,7 @@ extern struct netif *netif_default;
esp_netif_t* GetNetifCurrentDefault()
{
return netif_default;
return (esp_netif_t*)netif_default;
}
esp_netif_t* GetNetifByName(char *name)

View File

@ -233,9 +233,8 @@ esp_err_t my_esp_https_ota(const esp_http_client_config_t *config)
strcpy(FwUpdStatus, "<span class='clok'>Updated ok. Restart...</span>");
if (GetSysConf()->Flags1.bIsResetOTAEnabled)
{
ESP_LOGW(TAG, "Erasing NVS partition...");
ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(ResetInitSysConfig());
}
ESP_LOGI(TAG, "Firmware now restarting...");
vTaskDelay(pdMS_TO_TICKS(3000));

103
src/PPPoS.c Normal file
View File

@ -0,0 +1,103 @@
/*
* PPPoS.c
*
* Created on: Feb 10, 2025
* Author: bogd
*/
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "freertos/projdefs.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "netif/ppp/pppapi.h"
#include "netif/ppp/pppos.h"
#include "driver/uart.h"
#include "esp_netif.h"
#include <esp_log.h>
#define TAG "pppos"
// UART configuration
#define UART_PORT_NUM UART_NUM_2
#define UART_BAUD_RATE 115200
#define UART_RX_PIN 2
#define UART_TX_PIN 1
#define UART_BUF_SIZE 4096
#ifdef CONFIG_WEBGUIAPP_PPPOS_ENABLE
// PPP configuration
static ppp_pcb *ppp;
static struct netif ppp_netif;
// Function to handle PPP link status changes
static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
{
struct netif *pppif = (struct netif *)ctx;
if (err_code == PPPERR_NONE)
{
ESP_LOGI(TAG, "PPP connection established");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "IP address: %s", ip4addr_ntoa(netif_ip4_addr(pppif)));
ESP_LOGI(TAG, "Gateway: %s", ip4addr_ntoa(netif_ip4_gw(pppif)));
ESP_LOGI(TAG, "Netmask: %s", ip4addr_ntoa(netif_ip4_netmask(pppif)));
ESP_LOGI(TAG, "~~~~~~~~~~~");
return;
}
ESP_LOGI(TAG, "PPP connection lost");
}
// Function to output PPP data over UART
static u32_t pppos_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
uart_write_bytes(UART_PORT_NUM, (const char *)data, len);
return len;
}
static void uart_init()
{
uart_config_t uart_config = { .baud_rate = UART_BAUD_RATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE };
uart_param_config(UART_PORT_NUM, &uart_config);
uart_set_pin(UART_PORT_NUM, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_PORT_NUM, UART_BUF_SIZE * 2, 0, 0, NULL, 0);
}
static uint8_t data[UART_BUF_SIZE];
static void pppos_task(void *arg)
{
while (1)
{
int len = uart_read_bytes(UART_PORT_NUM, data, UART_BUF_SIZE, pdMS_TO_TICKS(10));
if (len > 0)
{
pppos_input(ppp, data, len);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void InitPPPSerial()
{
uart_init();
// Create PPPoS interface
ppp = pppapi_pppos_create(&ppp_netif, pppos_output_cb, ppp_link_status_cb, &ppp_netif);
if (ppp == NULL)
{
ESP_LOGE(TAG, "Failed to create PPPoS interface");
return;
}
// Set PPP as the default interface
pppapi_set_default(ppp);
// Connect PPP
pppapi_connect(ppp, 0);
xTaskCreate(pppos_task, "pppos_task", 4096 , (void *)0, 7, NULL);
}
#endif

View File

@ -30,6 +30,7 @@
#include "romfs.h"
#include "esp_idf_version.h"
#include "NetTransport.h"
#include "esp_vfs.h"
extern SYS_CONFIG SysConfig;
@ -43,7 +44,7 @@ void SetAppVars(rest_var_t *appvars, int size)
static void PrintInterfaceState(char *argres, int rw, esp_netif_t *netif)
{
snprintf(argres, MAX_DYNVAR_LENGTH,
snprintf(argres, VAR_MAX_VALUE_LENGTH,
(netif != NULL && esp_netif_is_netif_up(netif)) ? "\"CONNECTED\"" : "\"DISCONNECTED\"");
}
@ -71,11 +72,11 @@ static void funct_gsm_stat(char *argres, int rw)
static void funct_mqtt_1_stat(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, (GetMQTT1Connected()) ? "\"CONNECTED\"" : "\"DISCONNECTED\"");
snprintf(argres, VAR_MAX_VALUE_LENGTH, (GetMQTT1Connected()) ? "\"CONNECTED\"" : "\"DISCONNECTED\"");
}
static void funct_mqtt_2_stat(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, (GetMQTT2Connected()) ? "\"CONNECTED\"" : "\"DISCONNECTED\"");
snprintf(argres, VAR_MAX_VALUE_LENGTH, (GetMQTT2Connected()) ? "\"CONNECTED\"" : "\"DISCONNECTED\"");
}
static void funct_mqtt_1_test(char *argres, int rw)
{
@ -95,70 +96,86 @@ 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)
{
time_t now;
time(&now);
snprintf(argres, MAX_DYNVAR_LENGTH, "%d", (int) now);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) now);
}
static void funct_time_set(char *argres, int rw)
{
time_t unix = atoi(argres);
if (unix == 0)
{
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "\"ERROR_UNIX_TIME_NULL\"");
return;
}
struct timeval tv;
tv.tv_sec = unix;
SetSystemTimeVal(&tv, "Time set from user API");
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "\"TIME_SET_OK\"");
}
static void funct_uptime(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, "%d", (int) GetUpTime());
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) GetUpTime());
}
static void funct_wifi_level(char *argres, int rw)
{
wifi_ap_record_t wifi;
if (esp_wifi_sta_get_ap_info(&wifi) == ESP_OK)
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%ddBm\"", wifi.rssi);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%d dBm\"", wifi.rssi);
else
snprintf(argres, MAX_DYNVAR_LENGTH, "\"-\"");
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"-\"");
}
static void funct_fram(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, "%d", (int) esp_get_free_heap_size());
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) esp_get_free_heap_size());
}
static void funct_fram_min(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, "%d", (int) esp_get_minimum_free_heap_size());
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", (int) esp_get_minimum_free_heap_size());
}
static void funct_idf_ver(char *argres, int rw)
{
esp_app_desc_t cur_app_info;
if (esp_ota_get_partition_description(esp_ota_get_running_partition(), &cur_app_info) == ESP_OK)
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%s\"", cur_app_info.idf_ver);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", cur_app_info.idf_ver);
else
snprintf(argres, MAX_DYNVAR_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
}
static void funct_fw_ver(char *argres, int rw)
{
esp_app_desc_t cur_app_info;
if (esp_ota_get_partition_description(esp_ota_get_running_partition(), &cur_app_info) == ESP_OK)
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%s\"", cur_app_info.version);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", cur_app_info.version);
else
snprintf(argres, MAX_DYNVAR_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
}
static void funct_build_date(char *argres, int rw)
{
esp_app_desc_t cur_app_info;
if (esp_ota_get_partition_description(esp_ota_get_running_partition(), &cur_app_info) == ESP_OK)
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%s %s\"", cur_app_info.date, cur_app_info.time);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s %s\"", cur_app_info.date, cur_app_info.time);
else
snprintf(argres, MAX_DYNVAR_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", "ESP_ERR_NOT_SUPPORTED");
}
static void PrintMACFromInterface(char *argres, int rw, esp_netif_t *netif)
{
uint8_t mac_addr[6] = { 0 };
esp_netif_get_mac(netif, mac_addr);
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%02x-%02x-%02x-%02x-%02x-%02x\"",
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%02x-%02x-%02x-%02x-%02x-%02x\"",
mac_addr[0],
mac_addr[1],
mac_addr[2],
@ -214,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)
{
@ -232,8 +248,26 @@ void funct_gsm_imsi(char *argres, int rw)
{
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", GetPPPModemInfo()->imsi);
}
#endif
#ifdef CONFIG_WEBGUIAPP_MODEM_AT_ACCESS
void funct_gsm_at(char *argres, int rw)
{
char resp[1024];
resp[0] = 0x00;
ModemSendAT(argres, resp, 1000);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%s", resp);
}
void funct_gsm_at_timeout(char *argres, int rw)
{
ModemSetATTimeout(atoi(argres));
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"DONE\"");
}
#endif
void funct_gsm_rssi(char *argres, int rw)
{
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%d", PPPModemGetRSSI());
}
#endif
#ifdef CONFIG_WEBGUIAPP_LORAWAN_ENABLE
void funct_lora_stat(char *argres, int rw)
@ -262,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());
@ -274,71 +307,94 @@ static void funct_ota_start(char *argres, int rw)
}
static void funct_ota_newver(char *argres, int rw)
{
snprintf(argres, MAX_DYNVAR_LENGTH, "\"%s\"", GetAvailVersion());
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", GetAvailVersion());
}
//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));
}
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);
}
CronRecordsInterface(argres, rw);
}
//CRON implementation END
static void funct_serial_mode(char *argres, int rw)
{
#ifdef CONFIG_WEBGUIAPP_UART_MODE_UART
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"UART\"");
#elif CONFIG_WEBGUIAPP_UART_MODE_RS485
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"RS485\"");
#endif
}
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)
{
int res = ExecCommand(argres);
snprintf(argres, VAR_MAX_VALUE_LENGTH, "\"%s\"", EXEC_ERROR[res]);
}
static void funct_file_list(char *argres, int rw)
{
#if CONFIG_SDCARD_ENABLE
FileListHandler(argres, rw, "/sdcard/");
#else
FileListHandler(argres, rw, "/data/");
#endif
}
static void funct_file_block(char *argres, int rw)
{
#if CONFIG_SDCARD_ENABLE
FileBlockHandler(argres, rw, "/sdcard/");
#else
FileBlockHandler(argres, rw, "/data/");
#endif
}
#if CONFIG_SDCARD_ENABLE
static void funct_sd_list(char *argres, int rw)
{
FileListHandler(argres, rw, "/sdcard/");
}
static void funct_sd_block(char *argres, int rw)
{
FileBlockHandler(argres, rw, "/sdcard/");
}
#endif
static void funct_lat(char *argres, int rw)
{
if (rw)
ExecCommand(argres);
else
snprintf(argres, MAX_DYNVAR_LENGTH, "\"EXECUTED\"");
{
GetSysConf()->sntpClient.lat = atof(argres);
}
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%f", GetSysConf()->sntpClient.lat);
}
static void funct_lon(char *argres, int rw)
{
if (rw)
{
GetSysConf()->sntpClient.lon = atof(argres);
}
snprintf(argres, VAR_MAX_VALUE_LENGTH, "%f", GetSysConf()->sntpClient.lon);
}
const int hw_rev = CONFIG_BOARD_HARDWARE_REVISION;
@ -348,8 +404,9 @@ const bool VAR_FALSE = false;
const rest_var_t SystemVariables[] =
{
{ 0, "exec", &funct_exec, VAR_FUNCT, RW, 0, 0 },
{ 0, "exec", &funct_exec, VAR_FUNCT, RW, 0, 0 },
{ 0, "time", &funct_time, VAR_FUNCT, R, 0, 0 },
{ 0, "time_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 },
@ -360,8 +417,7 @@ const rest_var_t SystemVariables[] =
{ 0, "model_name", CONFIG_DEVICE_MODEL_NAME, VAR_STRING, R, 1, 64 },
{ 0, "hw_rev", ((int*) &hw_rev), VAR_INT, R, 1, 1024 },
{ 0, "build_date", CONFIG_DEVICE_MODEL_NAME, VAR_STRING, R, 1, 64 },
{ 0, "model_name", CONFIG_DEVICE_MODEL_NAME, VAR_STRING, R, 1, 64 },
//{ 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 },
@ -369,7 +425,6 @@ const rest_var_t SystemVariables[] =
{ 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 },
@ -392,6 +447,11 @@ 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 },
{ 0, "cronrecs_enab", &SysConfig.bIsCRONEnabled, VAR_BOOL, RW, 0, 1 },
#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 },
@ -452,16 +512,21 @@ const rest_var_t SystemVariables[] =
{ 0, "wifi_enab", &SysConfig.wifiSettings.Flags1.bIsWiFiEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "wifi_isdhcp", &SysConfig.wifiSettings.Flags1.bIsDHCPEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "wifi_power", &SysConfig.wifiSettings.MaxPower, VAR_INT, RW, 0, 80 },
{ 0, "wifi_disab_time", &SysConfig.wifiSettings.AP_disab_time, VAR_INT, RW, 0, 60 },
{ 0, "wifi_sta_mac", &funct_wifi_sta_mac, VAR_FUNCT, R, 0, 0 },
{ 0, "wifi_ap_mac", &funct_wifi_ap_mac, VAR_FUNCT, R, 0, 0 },
{ 0, "wifi_stat", &funct_wifi_stat, VAR_FUNCT, R, 0, 0 },
{ 0, "wifi_scan", &funct_wifiscan, VAR_FUNCT, R, 0, 0 },
{ 0, "wifi_scan_res", &funct_wifiscanres, VAR_FUNCT, R, 0, 0 },
{ 0, "wifi_level", &funct_wifi_level, VAR_FUNCT, R, 0, 0 },
#endif
#endif
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
{ 0, "gsm_enab", &SysConfig.gsmSettings.Flags1.bIsGSMEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "gsm_apn", &SysConfig.gsmSettings.APN, VAR_STRING, RW, 3, 31 },
{ 0, "gsm_apn_login", &SysConfig.gsmSettings.login, VAR_STRING, RW, 3, 31 },
{ 0, "gsm_apn_password", &SysConfig.gsmSettings.password, VAR_STRING, RW, 3, 31 },
{ 0, "gsm_module", &funct_gsm_module, VAR_FUNCT, R, 0, 0 },
{ 0, "gsm_operator", &funct_gsm_operator, VAR_FUNCT, R, 0, 0 },
{ 0, "gsm_imei", &funct_gsm_imei, VAR_FUNCT, R, 0, 0 },
@ -473,26 +538,35 @@ const rest_var_t SystemVariables[] =
{ 0, "gsm_dns2", &SysConfig.gsmSettings.DNSAddr2, VAR_IPADDR, RW, 0, 0 },
{ 0, "gsm_dns3", &SysConfig.gsmSettings.DNSAddr3, VAR_IPADDR, RW, 0, 0 },
{ 0, "gsm_stat", &funct_gsm_stat, VAR_FUNCT, R, 0, 0 },
#ifdef CONFIG_WEBGUIAPP_MODEM_AT_ACCESS
{ 0, "gsm_at_timeout", &funct_gsm_at_timeout, VAR_FUNCT, R, 0, 0 },
{ 0, "gsm_at", &funct_gsm_at, VAR_FUNCT, R, 0, 0 },
#endif
{ 0, "gsm_rssi", &funct_gsm_rssi, VAR_FUNCT, R, 0, 0 },
{ 0, "gsm_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
#else
{ 0, "gsm_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
#endif
#endif
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
{ 0, "serial_enab", &SysConfig.serialSettings.Flags.IsSerialEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "serial_bridge", &SysConfig.serialSettings.Flags.IsSerialEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "serial_mode", &SysConfig.serialSettings.Serialmode, VAR_INT, RW, 1, 2 },
{ 0, "serial_baud", &SysConfig.serialSettings.BaudRate, VAR_INT, RW, 1200, 4096000 },
{ 0, "serial_break", &SysConfig.serialSettings.InputBrake, VAR_INT, RW, 1, 50 },
{ 0, "serial_visible", (bool*) (&VAR_TRUE), VAR_BOOL, RW, 0, 1 },
#else
{ 0, "serial_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
#endif
{ 0, "serial_bridge", &SysConfig.serialSettings.Flags.IsBridgeEnabled, VAR_BOOL, RW, 0, 1 },
{ 0, "serial_mode", &funct_serial_mode, VAR_FUNCT, R, 1, 2 },
{ 0, "serial_baud", &SysConfig.serialSettings.BaudRate, VAR_INT, RW, 1200, 8192000 },
{ 0, "serial_bits", &SysConfig.serialSettings.DataBits, VAR_INT, RW, 0, 3 },
{ 0, "serial_parity", &SysConfig.serialSettings.Parity, VAR_INT, RW, 0, 3 },
{ 0, "serial_stop", &SysConfig.serialSettings.StopBits, VAR_INT, RW, 1, 3 },
{ 0, "serial_break", &SysConfig.serialSettings.InputBrake, VAR_INT, RW, 1, 50 },
{ 0, "serial_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
#else
{ 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 },
@ -500,12 +574,7 @@ const rest_var_t SystemVariables[] =
#else
{ 0, "lora_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
#endif
#endif
#ifdef CONFIG_WEBGUIAPP_MBTCP_ENABLED
{ 0, "mbtcp_enab", &SysConfig.modbusSettings.IsModbusTCPEnabled, VAR_BOOL, RW, 0, 1 },
@ -513,12 +582,21 @@ const rest_var_t SystemVariables[] =
{ 0, "mbtcp_visible", (bool*) (&VAR_TRUE), VAR_BOOL, R, 0, 1 },
#else
{ 0, "mbtcp_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 },
#endif
#endif
{ 0, "cronrecs", &funct_cronrecs, VAR_FUNCT, RW, 0, 0 },
{ 0, "objsinfo", &funct_objsinfo, VAR_FUNCT, R, 0, 0 },
};
{ 0, "file_list", &funct_file_list, 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)
{
@ -561,6 +639,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)
@ -630,6 +714,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;

View File

@ -113,15 +113,48 @@ void GetRFC3339Time(char *t)
timeinfo.tm_sec);
}
void GetISO8601Time(char *t)
{
struct tm timeinfo;
struct timeval tp;
gettimeofday(&tp, NULL);
localtime_r(&tp.tv_sec, &timeinfo);
sprintf(t, "%04d-%02d-%02dT%02d:%02d:%02d.%luZ",
(timeinfo.tm_year) + YEAR_BASE,
(timeinfo.tm_mon) + 1,
timeinfo.tm_mday,
timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec, (unsigned long)tp.tv_usec);
}
void StartSystemTimer(void)
{
ESP_ERROR_CHECK(esp_timer_create(&system_seconds_timer_args, &system_seconds_timer));
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)

View File

@ -16,8 +16,8 @@
* \version 1.0
* \date 2023-10-15
* \author Bogdan Pilyugin
* \brief
* \details
* \brief
* \details
* \copyright Apache License, Version 2.0
*/
@ -34,17 +34,26 @@
#include <sdkconfig.h>
#include <stdlib.h>
#include <string.h>
#include "SysConfiguration.h"
#include "webguiapp.h"
#include "driver/gpio.h"
#define TAG "serial_port"
#define UART_READ_TOUT (100) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks
#define PATTERN_CHR_NUM (3) /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "netif/ppp/pppapi.h"
#include "netif/ppp/pppos.h"
#include "esp_netif.h"
#define UART_TX_QUEUE_SIZE (5)
#define UART_RX_QUEUE_SIZE (5)
#define UART_DEBUG_MODE 0
#define TAG "serial_port"
#define UART_READ_TOUT (80) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks
#define PATTERN_CHR_NUM (3) /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/
#ifdef CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
#define UART_TX_QUEUE_SIZE (5)
#define UART_RX_QUEUE_SIZE (5)
#define UART_DEBUG_MODE 0
#if CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
QueueHandle_t UARTtxQueueHandle;
static StaticQueue_t xStaticUARTtxQueue;
@ -53,8 +62,11 @@ uint8_t UARTtxQueueStorageArea[UART_TX_QUEUE_SIZE * sizeof(UART_DATA_SEND_STRUCT
static QueueHandle_t uart_event_queue;
static char rxbuf[CONFIG_WEBGUIAPP_UART_BUF_SIZE];
esp_err_t TransmitSerialPort(char *data, int ln)
{
if(!GetSysConf()->serialSettings.Flags.IsSerialEnabled)
return ESP_ERR_NOT_ALLOWED;
UART_DATA_SEND_STRUCT DSS;
char *buf = malloc(ln);
if (!buf)
@ -83,7 +95,6 @@ static void ReceiveHandlerAPI()
M.outputDataBuffer = respbuf;
M.outputDataLength = EXPECTED_MAX_DATA_SIZE;
ServiceDataHandler(&M);
if (M.outputDataBuffer[0] != 0x00 && M.outputDataLength > 0)
{
TransmitSerialPort(M.outputDataBuffer, MIN(EXPECTED_MAX_DATA_SIZE, strlen(M.outputDataBuffer)));
@ -103,43 +114,42 @@ void serial_RX_task(void *arg)
for (;;)
{
//Waiting for UART event.
if (xQueueReceive(uart_event_queue, (void*) &event, portMAX_DELAY))
// Waiting for UART event.
if (xQueueReceive(uart_event_queue, (void *)&event, portMAX_DELAY))
{
#if UART_DEBUG_MODE == 1
ESP_LOGI(TAG, "uart[%d] event:%d", CONFIG_UART_PORT_NUM, event.type);
ESP_LOGI(TAG, "uart[%d] event:%d", CONFIG_WEBGUIAPP_UART_PORT_NUM, event.type);
#endif
switch (event.type)
{
//Event of UART receving data
// Event of UART receving data
/*We'd better handler data event fast, there would be much more data events than
other types of events. If we take too much time on data event, the queue might
be full.*/
case UART_DATA:
if (event.timeout_flag)
{
bzero(rxbuf, CONFIG_WEBGUIAPP_UART_BUF_SIZE);
uart_get_buffered_data_len(CONFIG_WEBGUIAPP_UART_PORT_NUM, (size_t*) &buffered_size);
uart_get_buffered_data_len(CONFIG_WEBGUIAPP_UART_PORT_NUM, (size_t *)&buffered_size);
if (buffered_size)
{
uart_read_bytes(CONFIG_WEBGUIAPP_UART_PORT_NUM, rxbuf, buffered_size, 100);
#if UART_DEBUG_MODE == 1
ESP_LOGI(TAG, "read of %d bytes: %s", buffered_size, rxbuf);
#endif
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();
}
}
break;
//Event of HW FIFO overflow detected
break;
// Event of HW FIFO overflow detected
case UART_FIFO_OVF:
#if UART_DEBUG_MODE == 1
@ -150,36 +160,36 @@ void serial_RX_task(void *arg)
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(CONFIG_WEBGUIAPP_UART_PORT_NUM);
xQueueReset(uart_event_queue);
break;
//Event of UART ring buffer full
break;
// Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGE(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(CONFIG_WEBGUIAPP_UART_PORT_NUM);
xQueueReset(uart_event_queue);
break;
//Event of UART RX break detected
break;
// Event of UART RX break detected
case UART_BREAK:
#if UART_DEBUG_MODE == 1
#if UART_DEBUG_MODE == 1
ESP_LOGI(TAG, "uart rx break");
#endif
break;
//Event of UART parity check error
break;
// Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGE(TAG, "uart parity error");
break;
//Event of UART frame error
break;
// Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGE(TAG, "uart frame error");
break;
//UART_PATTERN_DET
break;
// UART_PATTERN_DET
case UART_PATTERN_DET:
uart_get_buffered_data_len(CONFIG_WEBGUIAPP_UART_PORT_NUM, (size_t*) &buffered_size);
uart_get_buffered_data_len(CONFIG_WEBGUIAPP_UART_PORT_NUM, (size_t *)&buffered_size);
int pos = uart_pattern_pop_pos(CONFIG_WEBGUIAPP_UART_PORT_NUM);
#if UART_DEBUG_MODE == 1
ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", (int )pos, (int )buffered_size);
ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", (int)pos, (int)buffered_size);
#endif
if (pos == -1)
{
@ -200,11 +210,11 @@ void serial_RX_task(void *arg)
#endif
}
break;
//Others
break;
// Others
default:
ESP_LOGW(TAG, "uart event type: %d", event.type);
break;
break;
}
}
}
@ -217,8 +227,7 @@ void static serial_TX_task(void *arg)
while (1)
{
xQueueReceive(UARTtxQueueHandle, &DSS, portMAX_DELAY);
if (uart_write_bytes(CONFIG_WEBGUIAPP_UART_PORT_NUM, DSS.raw_data_ptr, DSS.data_length)
!= DSS.data_length)
if (uart_write_bytes(CONFIG_WEBGUIAPP_UART_PORT_NUM, DSS.raw_data_ptr, DSS.data_length) != DSS.data_length)
ESP_LOGE(TAG, "RS485 write data failure");
free(DSS.raw_data_ptr);
if (uart_wait_tx_done(CONFIG_WEBGUIAPP_UART_PORT_NUM, pdMS_TO_TICKS(1000)) != ESP_OK)
@ -229,41 +238,89 @@ void static serial_TX_task(void *arg)
void InitSerialPort(void)
{
uart_config_t uart_config = {
.baud_rate = GetSysConf()->serialSettings.BaudRate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
.baud_rate = GetSysConf()->serialSettings.BaudRate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
ESP_ERROR_CHECK(
uart_driver_install(CONFIG_WEBGUIAPP_UART_PORT_NUM, CONFIG_WEBGUIAPP_UART_BUF_SIZE * 2, 0, 20, &uart_event_queue, 0));
ESP_ERROR_CHECK(uart_param_config(CONFIG_WEBGUIAPP_UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(CONFIG_WEBGUIAPP_UART_PORT_NUM,
CONFIG_WEBGUIAPP_UART_TXD, CONFIG_WEBGUIAPP_UART_RXD, CONFIG_WEBGUIAPP_UART_RTS, -1));
//uart_config.data_bits = (uint8_t)GetSysConf()->serialSettings.DataBits;
if (GetSysConf()->serialSettings.Serialmode == 2)
ESP_ERROR_CHECK(uart_set_mode(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
else
ESP_ERROR_CHECK(uart_set_mode(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_MODE_UART));
switch (GetSysConf()->serialSettings.DataBits)
{
case 0:
uart_config.data_bits = UART_DATA_5_BITS;
break;
case 1:
uart_config.data_bits = UART_DATA_6_BITS;
break;
case 2:
uart_config.data_bits = UART_DATA_7_BITS;
break;
case 3:
uart_config.data_bits = UART_DATA_8_BITS;
break;
}
ESP_ERROR_CHECK(uart_enable_rx_intr(CONFIG_WEBGUIAPP_UART_PORT_NUM));
ESP_ERROR_CHECK(uart_set_rx_timeout(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_READ_TOUT));
//ESP_ERROR_CHECK(uart_enable_pattern_det_baud_intr(CONFIG_UART_PORT_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0));
switch (GetSysConf()->serialSettings.Parity)
{
case 0:
uart_config.parity = UART_PARITY_DISABLE;
break;
case 2:
uart_config.parity = UART_PARITY_EVEN;
break;
case 3:
uart_config.parity = UART_PARITY_ODD;
break;
}
switch (GetSysConf()->serialSettings.StopBits)
{
case 1:
uart_config.stop_bits = UART_STOP_BITS_1;
break;
case 2:
uart_config.stop_bits = UART_STOP_BITS_1_5;
break;
case 3:
uart_config.stop_bits = UART_STOP_BITS_2;
break;
}
// uart_config.stop_bits = (uint8_t) GetSysConf()->serialSettings.StopBits;
ESP_LOGI(TAG, "UART data_bits:%d parity:%d stop_bits:%d", GetSysConf()->serialSettings.DataBits, GetSysConf()->serialSettings.Parity, GetSysConf()->serialSettings.StopBits);
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_driver_install(CONFIG_WEBGUIAPP_UART_PORT_NUM, CONFIG_WEBGUIAPP_UART_BUF_SIZE * 2, 0, 20, &uart_event_queue, 0));
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_param_config(CONFIG_WEBGUIAPP_UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_set_pin(CONFIG_WEBGUIAPP_UART_PORT_NUM, CONFIG_WEBGUIAPP_UART_TXD, CONFIG_WEBGUIAPP_UART_RXD, CONFIG_WEBGUIAPP_UART_RTS, -1));
#ifdef CONFIG_WEBGUIAPP_UART_MODE_UART
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_set_mode(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_MODE_UART));
#elif CONFIG_WEBGUIAPP_UART_MODE_RS485
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_set_mode(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
#endif
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_enable_rx_intr(CONFIG_WEBGUIAPP_UART_PORT_NUM));
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_set_rx_timeout(CONFIG_WEBGUIAPP_UART_PORT_NUM, UART_READ_TOUT));
// ESP_ERROR_CHECK_WITHOUT_ABORT(uart_enable_pattern_det_baud_intr(CONFIG_UART_PORT_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0));
uart_pattern_queue_reset(CONFIG_WEBGUIAPP_UART_PORT_NUM, 20);
UARTtxQueueHandle = NULL;
UARTtxQueueHandle = xQueueCreateStatic(UART_TX_QUEUE_SIZE,
sizeof(UART_DATA_SEND_STRUCT),
UARTtxQueueStorageArea,
&xStaticUARTtxQueue);
UARTtxQueueHandle = xQueueCreateStatic(UART_TX_QUEUE_SIZE, sizeof(UART_DATA_SEND_STRUCT), UARTtxQueueStorageArea, &xStaticUARTtxQueue);
xTaskCreate(serial_TX_task, "serial_tx", 1024 * 2, (void*) 0, 7, NULL);
xTaskCreate(serial_RX_task, "serial_rx", 1024 * 4, (void*) 0, 12, NULL);
ESP_LOGI(TAG, "Serial port initialized on UART%d with baudrate %d", CONFIG_WEBGUIAPP_UART_PORT_NUM,
GetSysConf()->serialSettings.BaudRate);
xTaskCreate(serial_TX_task, "serial_tx", 4096 * 2, (void *)0, 7, NULL);
xTaskCreate(serial_RX_task, "serial_rx", 4096 * 4, (void *)0, 12, NULL);
ESP_LOGI(TAG, "Serial port initialized on UART%d with baudrate %d", CONFIG_WEBGUIAPP_UART_PORT_NUM, GetSysConf()->serialSettings.BaudRate);
}
#endif

123
src/ShiftRegisterSPI.c Normal file
View File

@ -0,0 +1,123 @@
/*
* ShiftRegisterSPI.c
*
* Created on: Apr 18, 2025
* Author: bogd
*/
#include "SysConfiguration.h"
#include "webguiapp.h"
#include "sdkconfig.h"
#include "esp_timer.h"
#ifdef CONFIG_WEBGUIAPP_SR_ENABLE
#define TAG "ShiftRegDriver"
#define CONFIG_SHIFTREG_SPI_HOST (1)
#define CONFIG_SHIFTREG_SPI_CLOCK_HZ (10000000)
#define CONFIG_SHIFTREG_SPI_CS_GPIO (12)
#define CONFIG_SHIFTREG_SAMPLES_MS (10)
static spi_device_handle_t spi_shift_handle;
static spi_transaction_t spi_shift_transaction;
static uint8_t inputs[] = { 0, 0 }, outputs[] = { 0, 0 };
static const int SHIFTREG_SAMPLE_START_BIT = BIT0;
static EventGroupHandle_t digio_event_group = NULL;
static SemaphoreHandle_t xSemaphoreShiftRegHandle = NULL;
static StaticSemaphore_t xSemaphoreShiftRegBuf;
esp_timer_handle_t shiftreg_timer, inputs_periodical_timer;
void ShiftRegSampleStart(void *arg);
const esp_timer_create_args_t shiftreg_timer_args = { .callback = &ShiftRegSampleStart, .name = "shiftregTimer" };
void ShiftRegSampleStart(void *arg)
{
xEventGroupSetBits(digio_event_group, SHIFTREG_SAMPLE_START_BIT);
}
static esp_err_t shiftreg_txrx_transaction(uint8_t *tx, uint8_t *rx, int bits)
{
memset(&spi_shift_transaction, 0, sizeof(spi_shift_transaction));
spi_shift_transaction.cmd = 0;
spi_shift_transaction.addr = 0;
spi_shift_transaction.length = bits;
spi_shift_transaction.tx_buffer = tx;
spi_shift_transaction.rx_buffer = rx;
spi_shift_transaction.rxlength = 0;
esp_err_t err = spi_device_polling_transmit(spi_shift_handle, &spi_shift_transaction);
ESP_ERROR_CHECK(err);
return err;
}
static void shift_reg_task(void *pvParameter)
{
while (1)
{
xEventGroupWaitBits(digio_event_group, SHIFTREG_SAMPLE_START_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
xSemaphoreTake(xSemaphoreShiftRegHandle, portMAX_DELAY);
shiftreg_txrx_transaction(outputs, inputs, 8);
xSemaphoreGive(xSemaphoreShiftRegHandle);
}
}
esp_err_t ShiftRegInit(void)
{
spi_device_interface_config_t devcfg = { .command_bits = 0, .address_bits = 0, .mode = 0, .clock_speed_hz = CONFIG_SHIFTREG_SPI_CLOCK_HZ, .queue_size = 10, .spics_io_num = 12 };
esp_err_t ret = spi_bus_add_device(CONFIG_SHIFTREG_SPI_HOST, &devcfg, &spi_shift_handle);
ESP_ERROR_CHECK(ret);
outputs[0] = 0b00110000;
digio_event_group = xEventGroupCreate();
xSemaphoreShiftRegHandle = xSemaphoreCreateBinaryStatic(&xSemaphoreShiftRegBuf);
xSemaphoreGive(xSemaphoreShiftRegHandle);
ESP_ERROR_CHECK(esp_timer_create(&shiftreg_timer_args, &shiftreg_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(shiftreg_timer, CONFIG_SHIFTREG_SAMPLES_MS * 1000));
ESP_LOGI(TAG, "HC595 SPI device init OK");
return ESP_OK;
}
esp_err_t vgpio_set_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level)
{
if (gpio_num < 0 || gpio_num >= VGPIO_NUM_MAX)
return ESP_ERR_INVALID_ARG;
uint8_t lv = *gpio_level & 1;
xSemaphoreTake(xSemaphoreShiftRegHandle, portMAX_DELAY);
outputs[0] = (outputs[0] & ~(1 << gpio_num)) | (lv << gpio_num);
shiftreg_txrx_transaction(outputs, inputs, 8);
xSemaphoreGive(xSemaphoreShiftRegHandle);
return ESP_OK;
}
esp_err_t vgpio_get_level(virtual_gpio_num_t gpio_num, uint8_t *gpio_level)
{
if (gpio_num < 0 || gpio_num >= VGPIO_NUM_MAX)
return ESP_ERR_INVALID_ARG;
*gpio_level = (outputs[0] & (1 << gpio_num)) ? 1 : 0;
return ESP_OK;
}
esp_err_t vgpio_set_reg(uint8_t reg)
{
if (xSemaphoreTake(xSemaphoreShiftRegHandle, pdMS_TO_TICKS(50)) == pdTRUE)
{
outputs[0] = (outputs[0] & 0b11110001) | (reg << 1);
shiftreg_txrx_transaction(outputs, inputs, 8);
xSemaphoreGive(xSemaphoreShiftRegHandle);
return ESP_OK;
}
else
{
ESP_LOGW(TAG, "Can't obtain SPI bus");
return ESP_ERR_NOT_FINISHED;
}
}
#endif

View File

@ -16,14 +16,15 @@
* \version 1.0
* \date 2023-07-26
* \author Bogdan Pilyugin
* \brief
* \details
* \brief
* \details
* \copyright Apache License, Version 2.0
*/
#include "webguiapp.h"
#include "SystemApplication.h"
#include "mbedtls/md.h"
#include <string.h>
#define TAG "SysComm"
@ -54,18 +55,19 @@ 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);
jwObj_string(&jwc, "payloadname", MSG->parsedData.payloadName);
jwObj_object(&jwc, "payload");
jwObj_int(&jwc, "applytype", 0);
jwObj_object(&jwc, "variables");
jRead(MSG->inputDataBuffer, "{'data'{'payload'{'variables'", &result);
if (result.dataType == JREAD_OBJECT)
{ //Write variables
{ // Write variables
char VarName[VAR_MAX_NAME_LENGTH];
char *VarValue = malloc(VAR_MAX_VALUE_LENGTH);
if (!VarValue)
@ -73,9 +75,7 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
for (int i = 0; i < result.elements; ++i)
{
jRead_string(MSG->inputDataBuffer, "{'data'{'payload'{'variables'{*", VarName,
VAR_MAX_NAME_LENGTH,
&i);
jRead_string(MSG->inputDataBuffer, "{'data'{'payload'{'variables'{*", VarName, VAR_MAX_NAME_LENGTH, &i);
const char parsevar[] = "{'data'{'payload'{'variables'{'";
char expr[sizeof(parsevar) + VAR_MAX_NAME_LENGTH];
strcpy(expr, parsevar);
@ -89,25 +89,30 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
esp_err_t res = ESP_ERR_INVALID_ARG;
rest_var_types tp = VAR_ERROR;
if (MSG->parsedData.msgType == DATA_MESSAGE_TYPE_COMMAND)
{ //Write variables
{ // Write variables
res = SetConfVar(VarName, VarValue, &tp);
if (res == ESP_OK)
GetConfVar(VarName, VarValue, &tp);
else
strcpy(VarValue, esp_err_to_name(res));
if (tp != VAR_FUNCT)
{
if (res == ESP_OK)
GetConfVar(VarName, VarValue, &tp);
else
{
strcpy(VarValue, esp_err_to_name(res));
tp = VAR_ERROR;
}
}
}
else
{ //Read variables
{ // Read variables
res = GetConfVar(VarName, VarValue, &tp);
if (res != ESP_OK)
strcpy(VarValue, esp_err_to_name(res));
}
//Response with actual data
// Response with actual data
if (tp == VAR_STRING || tp == VAR_IPADDR || tp == VAR_ERROR || tp == VAR_PASS)
jwObj_string(&jwc, VarName, VarValue);
else
jwObj_raw(&jwc, VarName, VarValue);
}
free(VarValue);
}
@ -116,24 +121,23 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
jwEnd(&jwc);
jwEnd(&jwc);
GetSysErrorDetales((sys_error_code) MSG->err_code, &err_br, &err_desc);
jwObj_string(&jwc, "error", (char*) err_br);
jwObj_string(&jwc, "error_descr", (char*) err_desc);
//GetSysErrorDetales((sys_error_code)MSG->err_code, &err_br, &err_desc);
//jwObj_string(&jwc, "error", (char *)err_br);
//jwObj_string(&jwc, "error_descr", (char *)err_desc);
jwEnd(&jwc);
char *datap = strstr(MSG->outputDataBuffer, "\"data\":");
if (datap)
{
datap += sizeof("\"data\":") - 1;
SHA256hmacHash((unsigned char*) datap, strlen(datap), (unsigned char*) "mykey", sizeof("mykey"),
MSG->parsedData.sha256);
SHA256hmacHash((unsigned char *)datap, strlen(datap), (unsigned char *)"mykey", sizeof("mykey"), MSG->parsedData.sha256);
unsigned char sha_print[32 * 2 + 1];
BytesToStr(MSG->parsedData.sha256, sha_print, 32);
sha_print[32 * 2] = 0x00;
#if REAST_API_DEBUG_MODE
ESP_LOGI(TAG, "SHA256 of DATA object is %s", sha_print);
#endif
jwObj_string(&jwc, "signature", (char*) sha_print);
jwObj_string(&jwc, "signature", (char *)sha_print);
}
else
return SYS_ERROR_SHA256_DATA;
@ -143,7 +147,7 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
jRead(MSG->inputDataBuffer, "{'data'{'payload'{'applytype'", &result);
if (result.elements == 1)
{
int atype = atoi((char*) result.pValue);
int atype = atoi((char *)result.pValue);
switch (atype)
{
case 0:
@ -152,17 +156,16 @@ static sys_error_code PayloadDefaultTypeHandler(data_message_t *MSG)
WriteNVSSysConfig(GetSysConf());
if (CustomSaveConf != NULL)
CustomSaveConf();
break;
break;
case 2:
WriteNVSSysConfig(GetSysConf());
if (CustomSaveConf != NULL)
CustomSaveConf();
DelayedRestart();
break;
break;
default:
return SYS_ERROR_PARSE_APPLYTYPE;
}
}
else
{
@ -187,8 +190,7 @@ static sys_error_code DataHeaderParser(data_message_t *MSG)
jRead_string(MSG->inputDataBuffer, "{'data'", hashbuf, MSG->inputDataLength, 0);
if (strlen(hashbuf) > 0)
{
SHA256hmacHash((unsigned char*) hashbuf, strlen(hashbuf), (unsigned char*) "mykey", sizeof("mykey"),
MSG->parsedData.sha256);
SHA256hmacHash((unsigned char *)hashbuf, strlen(hashbuf), (unsigned char *)"mykey", sizeof("mykey"), MSG->parsedData.sha256);
unsigned char sha_print[32 * 2 + 1];
BytesToStr(MSG->parsedData.sha256, sha_print, 32);
sha_print[32 * 2] = 0x00;
@ -207,15 +209,15 @@ static sys_error_code DataHeaderParser(data_message_t *MSG)
if (result.elements == 1)
{
#if REAST_API_DEBUG_MODE
ESP_LOGI(TAG, "Signature is %.*s", 64, (char* )result.pValue);
ESP_LOGI(TAG, "Signature is %.*s", 64, (char *)result.pValue);
#endif
//Here compare calculated and received signature;
// Here compare calculated and received signature;
}
else
return SYS_ERROR_PARSE_SIGNATURE;
//Extract 'messidx' or throw exception
// Extract 'messidx' or throw exception
jRead(MSG->inputDataBuffer, "{'data'{'msgid'", &result);
if (result.elements == 1)
{
@ -242,11 +244,11 @@ static sys_error_code DataHeaderParser(data_message_t *MSG)
else
strcpy(MSG->parsedData.dstID, "FFFFFFFF");
//Extract 'msgtype' or throw exception
// Extract 'msgtype' or throw exception
jRead(MSG->inputDataBuffer, "{'data'{'msgtype'", &result);
if (result.elements == 1)
{
MSG->parsedData.msgType = atoi((char*) result.pValue);
MSG->parsedData.msgType = atoi((char *)result.pValue);
if (MSG->parsedData.msgType > DATA_MESSAGE_TYPE_RESPONSE || MSG->parsedData.msgType < DATA_MESSAGE_TYPE_COMMAND)
return SYS_ERROR_PARSE_MSGTYPE;
if (MSG->parsedData.msgType == DATA_MESSAGE_TYPE_RESPONSE)
@ -255,21 +257,29 @@ static sys_error_code DataHeaderParser(data_message_t *MSG)
else
return SYS_ERROR_PARSE_MSGTYPE;
//Extract 'payloadtype' or throw exception
// Extract 'payloadtype' or throw exception
jRead(MSG->inputDataBuffer, "{'data'{'payloadtype'", &result);
if (result.elements == 1)
{
MSG->parsedData.payloadType = atoi((char*) result.pValue);
MSG->parsedData.payloadType = atoi((char *)result.pValue);
}
else
return SYS_ERROR_PARSE_PAYLOADTYPE;
jRead(MSG->inputDataBuffer, "{'data'{'payloadname'", &result);
if (result.elements == 1)
{
jRead_string(MSG->inputDataBuffer, "{'data'{'payloadname'", MSG->parsedData.payloadName, 31, 0);
}
else
strcpy(MSG->parsedData.payloadName, "notset");
sys_error_code err = SYS_ERROR_HANDLER_NOT_SET;
switch (MSG->parsedData.payloadType)
{
case PAYLOAD_DEFAULT:
err = PayloadDefaultTypeHandler(MSG);
break;
break;
}
if (err != SYS_ERROR_HANDLER_NOT_SET)
return err;
@ -304,9 +314,9 @@ esp_err_t ServiceDataHandler(data_message_t *MSG)
if (MSG->err_code == SYS_GOT_RESPONSE_MESSAGE)
{
//ToDo Here handler of received data
// ToDo Here handler of received data
#if REAST_API_DEBUG_MODE
ESP_LOGI(TAG, "Got response message with msgid=%d", MSG->parsedData.msgID);
ESP_LOGI(TAG, "Got response message with msgid=%d", (int)MSG->parsedData.msgID);
#endif
MSG->outputDataBuffer[0] = 0x00;
MSG->outputDataLength = 0;
@ -320,15 +330,15 @@ 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;
const char *err_desc;
GetSysErrorDetales((sys_error_code) MSG->err_code, &err_br, &err_desc);
jwObj_string(&jwc, "error", (char*) err_br);
jwObj_string(&jwc, "error_descr", (char*) err_desc);
GetSysErrorDetales((sys_error_code)MSG->err_code, &err_br, &err_desc);
jwObj_string(&jwc, "error", (char *)err_br);
jwObj_string(&jwc, "error_descr", (char *)err_desc);
jwEnd(&jwc);
jwClose(&jwc);
}

View File

@ -23,6 +23,7 @@
#include "../include/SysConfiguration.h"
#include "ShiftRegisterSPI.h"
#include "SystemApplication.h"
#include <webguiapp.h>
#include "stdlib.h"
@ -33,6 +34,7 @@
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/i2c.h"
#include <driver/uart.h>
#include "romfs.h"
#include "spifs.h"
@ -72,6 +74,7 @@ static void InitSysIO(void);
static void InitSysSPI(void);
static void InitSysI2C(void);
esp_err_t spi_device_polling_transmit_synchronized(spi_device_handle_t handle,
spi_transaction_t *trans_desc)
{
@ -96,9 +99,17 @@ esp_err_t WebGuiAppInit(void)
#if CONFIG_WEBGUIAPP_SPI_ENABLE
InitSysSPI();
#endif
#ifdef CONFIG_WEBGUIAPP_SR_ENABLE
ShiftRegInit();
#endif
#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());
@ -106,7 +117,7 @@ esp_err_t WebGuiAppInit(void)
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND
||
MANUAL_RESET == 1
#if (MAIN_FUNCTIONAL_BUTTON_GPIO >= 0)
#if (MAIN_FUNCTIONAL_BUTTON_GPIO >= 0)
|| gpio_get_level(MAIN_FUNCTIONAL_BUTTON_GPIO) == 0
#endif
)
@ -157,7 +168,8 @@ 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());
StartTimeGet();
if (GetSysConf()->sntpClient.Flags1.bIsGlobalEnabled)
StartTimeGet();
//regTimeSyncCallback(&TimeObtainHandler);
//mDNSServiceStart();
@ -171,10 +183,14 @@ esp_err_t WebGuiAppInit(void)
#endif
#if CONFIG_WEBGUIAPP_UART_TRANSPORT_ENABLE
InitSerialPort();
if(GetSysConf()->serialSettings.Flags.IsSerialEnabled)
InitSerialPort();
#endif
#ifdef CONFIG_WEBGUIAPP_PPPOS_ENABLE
InitPPPSerial();
#endif
return ESP_OK;
}
@ -249,7 +265,7 @@ static void ResetSysConfig(SYS_CONFIG *Conf)
UINT32_VAL d;
GetChipId((uint8_t*) d.v);
snprintf(Conf->SN, 11, "%010u", (unsigned int)swap(d.Val));
snprintf(Conf->SN, 11, "%010u", (unsigned int) swap(d.Val));
Conf->ColorSheme = CONFIG_WEBGUIAPP_DEFAULT_COLOR_SCHEME;
@ -310,6 +326,7 @@ static void ResetSysConfig(SYS_CONFIG *Conf)
esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT,
(esp_ip4_addr_t*) &Conf->wifiSettings.DNSAddr3);
Conf->wifiSettings.MaxPower = 80;
Conf->wifiSettings.AP_disab_time = 10;
#endif
#if CONFIG_WEBGUIAPP_ETHERNET_ENABLE
@ -333,7 +350,14 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
#endif
#if CONFIG_WEBGUIAPP_GPRS_ENABLE
Conf->gsmSettings.Flags1.bIsGSMEnabled = false;
#if CONFIG_WEBGUIAPP_GPRS_ON
Conf->gsmSettings.Flags1.bIsGSMEnabled = true;
#endif
memcpy(Conf->gsmSettings.APN, CONFIG_MODEM_PPP_APN,sizeof(CONFIG_MODEM_PPP_APN));
memcpy(Conf->gsmSettings.login, CONFIG_MODEM_PPP_APN,sizeof(CONFIG_MODEM_PPP_APN));
memcpy(Conf->gsmSettings.password, CONFIG_MODEM_PPP_APN,sizeof(CONFIG_MODEM_PPP_APN));
esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS1_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &Conf->gsmSettings.DNSAddr1);
esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS2_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &Conf->gsmSettings.DNSAddr2);
esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &Conf->gsmSettings.DNSAddr3);
@ -353,23 +377,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
@ -382,6 +412,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;
@ -406,6 +438,9 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
#endif
Conf->serialSettings.Serialmode = 1;
Conf->serialSettings.BaudRate = CONFIG_WEBGUIAPP_UART_BAUD_RATE;
Conf->serialSettings.DataBits = UART_DATA_8_BITS;
Conf->serialSettings.Parity = UART_PARITY_DISABLE;
Conf->serialSettings.StopBits = UART_STOP_BITS_1;
Conf->serialSettings.InputBrake = 50;
#endif
@ -416,17 +451,24 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C
#endif
Conf->modbusSettings.ModbusTCPPort = CONFIG_WEBGUIAPP_MBTCP_SERVER_PORT;
#endif
for (int i = 0; i < CONFIG_WEBGUIAPP_CRON_NUMBER; i++ )
for (int i = 0; i < CONFIG_WEBGUIAPP_CRON_NUMBER; i++)
{
Conf->Timers[i].num = i+1;
Conf->Timers[i].num = i + 1;
Conf->Timers[i].del = true;
Conf->Timers[i].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");
}
Conf->bIsCRONEnabled = true;
#ifdef CONFIG_WEBGUIAPP_ASTRO_ENABLE
#endif
}
esp_err_t ReadNVSSysConfig(SYS_CONFIG *SysConf)
@ -554,7 +596,7 @@ void DelayedRestartTask(void *pvParameter)
void DelayedRestart(void)
{
xTaskCreate(DelayedRestartTask, "RestartTask", 1024 * 4, (void*) 0, 3,
NULL);
NULL);
}
bool GetUserAppNeedReset(void)
@ -567,10 +609,74 @@ 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];
char tstamp[16];
char tstamp[ISO8601_TIMESTAMP_LENGTH + 2];
strcpy(filename, "/data/");
strcat(filename, fname);
FILE *f = fopen(filename, "a");
@ -583,9 +689,11 @@ void LogFile(char *fname, char *format, ...)
va_start(arg, format);
va_end(arg);
strcpy(tstamp, "\r\n");
strcat(tstamp, esp_log_system_timestamp());
char ts[ISO8601_TIMESTAMP_LENGTH];
GetISO8601Time(ts);
strcat(tstamp, ts);
strcat(tstamp, " ");
fwrite(tstamp, 1, 15, f);
fwrite(tstamp, 1, strlen(tstamp), f);
vfprintf(f, format, arg);
fclose(f);
ESP_LOGI(TAG, "File written to %s", filename);

View File

@ -16,7 +16,7 @@
* Project: ChargePointMainboard
* Created on: 2022-07-21
* Author: Bogdan Pilyugin
* Description:
* Description:
*/
#include <SysConfiguration.h>
@ -39,24 +39,24 @@ esp_netif_t *ap_netif;
static const char *TAG = "WiFiTransport";
#define WIFI_CONNECT_AFTER_FAIL_DELAY 40
#define WIFI_AP_ONBOOT_TIME 300
#define WIFI_CONNECT_AFTER_FAIL_DELAY 40
#define WIFI_AP_ONBOOT_TIME 300
#define EXAMPLE_ESP_MAXIMUM_RETRY 5
#define EXAMPLE_ESP_WIFI_CHANNEL 6
#define EXAMPLE_MAX_STA_CONN 10
#define EXAMPLE_ESP_MAXIMUM_RETRY 5
#define EXAMPLE_ESP_WIFI_CHANNEL 6
#define EXAMPLE_MAX_STA_CONN 10
static bool isWiFiRunning = false;
static bool isWiFiConnected = false;
static bool isWiFiGotIp = false;
static bool isWiFiFail = false;
static int TempAPCounter = WIFI_AP_ONBOOT_TIME;
static int TempAPCounter = 0;
#define DEFAULT_SCAN_LIST_SIZE 20
static wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
static bool isScanExecuting = false;
wifi_ap_record_t* GetWiFiAPRecord(uint8_t n)
wifi_ap_record_t *GetWiFiAPRecord(uint8_t n)
{
if (n < DEFAULT_SCAN_LIST_SIZE)
{
@ -65,12 +65,12 @@ wifi_ap_record_t* GetWiFiAPRecord(uint8_t n)
return NULL;
}
esp_netif_t* GetSTANetifAdapter(void)
esp_netif_t *GetSTANetifAdapter(void)
{
return sta_netif;
}
esp_netif_t* GetAPNetifAdapter(void)
esp_netif_t *GetAPNetifAdapter(void)
{
return ap_netif;
}
@ -87,9 +87,7 @@ void resonnectWithDelay(void *agr)
vTaskDelete(NULL);
}
static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id,
void *event_data)
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
@ -116,12 +114,11 @@ static void event_handler(void *arg, esp_event_base_t event_base,
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_BEACON_TIMEOUT)
{
ESP_LOGW(TAG, "STA beacon timeout");
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t*) event_data;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
memcpy(&GetSysConf()->wifiSettings.InfIPAddr, &event->ip_info.ip, sizeof(event->ip_info.ip));
memcpy(&GetSysConf()->wifiSettings.InfMask, &event->ip_info.netmask, sizeof(event->ip_info.netmask));
@ -136,7 +133,7 @@ static void event_handler(void *arg, esp_event_base_t event_base,
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t*) event_data;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
const esp_netif_ip_info_t *ip_info = &event->ip_info;
memcpy(&GetSysConf()->wifiSettings.InfIPAddr, &event->ip_info.ip, sizeof(event->ip_info.ip));
memcpy(&GetSysConf()->wifiSettings.InfMask, &event->ip_info.netmask, sizeof(event->ip_info.netmask));
@ -152,30 +149,26 @@ static void event_handler(void *arg, esp_event_base_t event_base,
else if (event_id == WIFI_EVENT_AP_STACONNECTED)
{
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
ESP_LOGI(TAG, "station " MACSTR " join, AID=%d", MAC2STR(event->mac), event->aid);
}
else if (event_id == WIFI_EVENT_AP_STADISCONNECTED)
{
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
ESP_LOGI(TAG, "station " MACSTR " leave, AID=%d", MAC2STR(event->mac), event->aid);
}
}
static void wifi_init_softap(void *pvParameter)
{
char if_key_str[24];
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP()
;
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP();
strcpy(if_key_str, "WIFI_AP_USER");
esp_netif_conf.if_key = if_key_str;
esp_netif_conf.route_prio = AP_PRIO;
esp_netif_config_t cfg_netif = {
.base = &esp_netif_conf,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP
};
esp_netif_config_t cfg_netif = { .base = &esp_netif_conf, .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP };
ap_netif = esp_netif_new(&cfg_netif);
assert(ap_netif);
@ -196,15 +189,10 @@ static void wifi_init_softap(void *pvParameter)
esp_netif_attach_wifi_ap(ap_netif);
esp_wifi_set_default_wifi_ap_handlers();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT()
;
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));
wifi_config_t wifi_config = {
.ap = {
@ -220,8 +208,7 @@ static void wifi_init_softap(void *pvParameter)
}
memcpy(wifi_config.ap.ssid, GetSysConf()->wifiSettings.ApSSID, strlen(GetSysConf()->wifiSettings.ApSSID));
memcpy(wifi_config.ap.password, GetSysConf()->wifiSettings.ApSecurityKey,
strlen(GetSysConf()->wifiSettings.ApSecurityKey));
memcpy(wifi_config.ap.password, GetSysConf()->wifiSettings.ApSecurityKey, strlen(GetSysConf()->wifiSettings.ApSecurityKey));
wifi_config.ap.ssid_len = strlen(GetSysConf()->wifiSettings.ApSSID);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
@ -238,16 +225,13 @@ static void wifi_init_softap(void *pvParameter)
static void wifi_init_sta(void *pvParameter)
{
//sta_netif = esp_netif_create_default_wifi_sta();
// sta_netif = esp_netif_create_default_wifi_sta();
char if_key_str[24];
esp_netif_inherent_config_t esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
strcpy(if_key_str, "WIFI_STA_USER");
esp_netif_conf.if_key = if_key_str;
esp_netif_conf.route_prio = STA_PRIO;
esp_netif_config_t cfg_netif = {
.base = &esp_netif_conf,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA
};
esp_netif_config_t cfg_netif = { .base = &esp_netif_conf, .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA };
sta_netif = esp_netif_new(&cfg_netif);
assert(sta_netif);
@ -262,7 +246,7 @@ static void wifi_init_sta(void *pvParameter)
esp_netif_set_ip_info(sta_netif, &ip_info);
esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_MAIN, &dns_info);
//esp_netif_str_to_ip4(&GetSysConf()->wifiSettings.DNSAddr3, (esp_ip4_addr_t*)(&dns_info.ip));
// esp_netif_str_to_ip4(&GetSysConf()->wifiSettings.DNSAddr3, (esp_ip4_addr_t*)(&dns_info.ip));
memcpy(&dns_info.ip, &GetSysConf()->wifiSettings.DNSAddr3, sizeof(esp_ip4_addr_t));
esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_FALLBACK, &dns_info);
@ -273,22 +257,13 @@ static void wifi_init_sta(void *pvParameter)
esp_netif_attach_wifi_station(sta_netif);
esp_wifi_set_default_wifi_sta_handlers();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT()
;
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
@ -304,8 +279,9 @@ static void wifi_init_sta(void *pvParameter)
},
};
memcpy(wifi_config.sta.ssid, GetSysConf()->wifiSettings.InfSSID, strlen(GetSysConf()->wifiSettings.InfSSID));
memcpy(wifi_config.sta.password, GetSysConf()->wifiSettings.InfSecurityKey,
strlen(GetSysConf()->wifiSettings.InfSecurityKey));
memcpy(wifi_config.sta.password, GetSysConf()->wifiSettings.InfSecurityKey, strlen(GetSysConf()->wifiSettings.InfSecurityKey));
esp_netif_set_hostname(sta_netif, GetSysConf()->NetBIOSName);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
@ -321,39 +297,32 @@ static void wifi_init_sta(void *pvParameter)
static void wifi_init_apsta(void *pvParameter)
{
//BEGIN AP MODE IF
// BEGIN AP MODE IF
char ap_if_key_str[24];
esp_netif_inherent_config_t ap_esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP()
;
esp_netif_inherent_config_t ap_esp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP();
strcpy(ap_if_key_str, "WIFI_AP_USER");
ap_esp_netif_conf.if_key = ap_if_key_str;
ap_esp_netif_conf.route_prio = AP_PRIO;
esp_netif_config_t cfg_netif = {
.base = &ap_esp_netif_conf,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP
};
esp_netif_config_t cfg_netif = { .base = &ap_esp_netif_conf, .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP };
ap_netif = esp_netif_new(&cfg_netif);
assert(ap_netif);
//END AP MODE IF
// END AP MODE IF
//BEGIN STA MODE IF
// BEGIN STA MODE IF
char sta_if_key_str[24];
esp_netif_inherent_config_t staesp_netif_conf = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
strcpy(sta_if_key_str, "WIFI_STA_USER");
staesp_netif_conf.if_key = sta_if_key_str;
staesp_netif_conf.route_prio = STA_PRIO;
esp_netif_config_t sta_cfg_netif = {
.base = &staesp_netif_conf,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA
};
esp_netif_config_t sta_cfg_netif = { .base = &staesp_netif_conf, .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA };
sta_netif = esp_netif_new(&sta_cfg_netif);
assert(sta_netif);
//END STA MODE IF
// END STA MODE IF
//BEGIN AP MODE CONFIGURATION
// BEGIN AP MODE CONFIGURATION
esp_netif_ip_info_t ip_info;
memcpy(&ip_info.ip, &GetSysConf()->wifiSettings.ApIPAddr, 4);
memcpy(&ip_info.gw, &GetSysConf()->wifiSettings.ApIPAddr, 4);
@ -370,22 +339,20 @@ static void wifi_init_apsta(void *pvParameter)
esp_netif_attach_wifi_ap(ap_netif);
esp_wifi_set_default_wifi_ap_handlers();
wifi_init_config_t ap_cfg = WIFI_INIT_CONFIG_DEFAULT()
;
wifi_init_config_t ap_cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&ap_cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
NULL));
wifi_config_t ap_wifi_config = {
.ap = {
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
.authmode = WIFI_AUTH_WPA_WPA2_PSK,
/*
.pmf_cfg = {
.capable = false,
.required = false}
*/
},
};
if (strlen(CONFIG_WEBGUIAPP_WIFI_KEY_AP) == 0)
@ -394,13 +361,12 @@ static void wifi_init_apsta(void *pvParameter)
}
memcpy(ap_wifi_config.ap.ssid, GetSysConf()->wifiSettings.ApSSID, strlen(GetSysConf()->wifiSettings.ApSSID));
memcpy(ap_wifi_config.ap.password, GetSysConf()->wifiSettings.ApSecurityKey,
strlen(GetSysConf()->wifiSettings.ApSecurityKey));
memcpy(ap_wifi_config.ap.password, GetSysConf()->wifiSettings.ApSecurityKey, strlen(GetSysConf()->wifiSettings.ApSecurityKey));
ap_wifi_config.ap.ssid_len = strlen(GetSysConf()->wifiSettings.ApSSID);
//END AP MODE CONFIGURATION
// END AP MODE CONFIGURATION
//BEGIN STA MODE CONFIGURATION
//esp_netif_ip_info_t ip_info;
// BEGIN STA MODE CONFIGURATION
// esp_netif_ip_info_t ip_info;
memcpy(&ip_info.ip, &GetSysConf()->wifiSettings.InfIPAddr, 4);
memcpy(&ip_info.gw, &GetSysConf()->wifiSettings.InfGateway, 4);
memcpy(&ip_info.netmask, &GetSysConf()->wifiSettings.InfMask, 4);
@ -411,7 +377,7 @@ static void wifi_init_apsta(void *pvParameter)
esp_netif_set_ip_info(sta_netif, &ip_info);
esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_MAIN, &sta_dns_info);
//esp_netif_str_to_ip4(&GetSysConf()->wifiSettings.DNSAddr3, (esp_ip4_addr_t*)(&dns_info.ip));
// esp_netif_str_to_ip4(&GetSysConf()->wifiSettings.DNSAddr3, (esp_ip4_addr_t*)(&dns_info.ip));
memcpy(&sta_dns_info.ip, &GetSysConf()->wifiSettings.DNSAddr3, sizeof(esp_ip4_addr_t));
esp_netif_set_dns_info(sta_netif, ESP_NETIF_DNS_FALLBACK, &sta_dns_info);
@ -422,22 +388,13 @@ static void wifi_init_apsta(void *pvParameter)
esp_netif_attach_wifi_station(sta_netif);
esp_wifi_set_default_wifi_sta_handlers();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT()
;
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
wifi_config_t sta_wifi_config = {
.sta = {
@ -446,20 +403,29 @@ static void wifi_init_apsta(void *pvParameter)
* doesn't support WPA2, these mode can be enabled by commenting below line */
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {
.capable = true,
.required = false
},
/*
.pmf_cfg = {
.capable = false,
.required = false
},
*/
},
};
memcpy(sta_wifi_config.sta.ssid, GetSysConf()->wifiSettings.InfSSID, strlen(GetSysConf()->wifiSettings.InfSSID));
memcpy(sta_wifi_config.sta.password, GetSysConf()->wifiSettings.InfSecurityKey,
strlen(GetSysConf()->wifiSettings.InfSecurityKey));
//END STA MODE CONFIGURATION
memcpy(sta_wifi_config.sta.password, GetSysConf()->wifiSettings.InfSecurityKey, strlen(GetSysConf()->wifiSettings.InfSecurityKey));
// END STA MODE CONFIGURATION
ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "test_TEST"));
ESP_ERROR_CHECK(esp_netif_set_hostname(ap_netif, GetSysConf()->NetBIOSName));
char name[32];
esp_netif_get_hostname(sta_netif, (const char**)(&name));
ESP_LOGW(TAG, "Net bios name set to %s", name);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_wifi_config));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_wifi_config));
esp_wifi_disable_pmf_config(WIFI_IF_STA);
esp_wifi_disable_pmf_config(WIFI_IF_AP);
ESP_ERROR_CHECK(esp_wifi_start());
int max_power = GetSysConf()->wifiSettings.MaxPower;
@ -468,8 +434,7 @@ static void wifi_init_apsta(void *pvParameter)
wifi_country_t CC;
esp_wifi_get_country(&CC);
ESP_LOGI(TAG, "Country code %.*s, start_ch=%d, total_ch=%d, max power %d", 3, CC.cc, CC.schan, CC.nchan,
CC.max_tx_power);
ESP_LOGI(TAG, "Country code %.*s, start_ch=%d, total_ch=%d, max power %d", 3, CC.cc, CC.schan, CC.nchan, CC.max_tx_power);
ESP_LOGI(TAG, "wifi_init_softap_sta finished");
vTaskDelete(NULL);
@ -485,35 +450,41 @@ void WiFiConnect(void)
esp_wifi_connect();
}
#define RECONNECT_INTERVAL 10
#define WAITIP_INTERVAL 10
#define RECONNECT_INTERVAL_AP 30
#define RECONNECT_INTERVAL_STA 30
#define RECONNECT_FAST_ATTEMPTS 5
#define WAITIP_INTERVAL 10
static void WiFiControlTask(void *arg)
{
//WiFi init and start block
static int reconnect_counter = RECONNECT_INTERVAL;
// WiFi init and start block
static int attempts = 0;
static int reconnect_counter;
reconnect_counter = 5;
static int waitip_counter = WAITIP_INTERVAL;
//s_wifi_event_group = xEventGroupCreate();
// s_wifi_event_group = xEventGroupCreate();
switch (GetSysConf()->wifiSettings.WiFiMode)
{
case WIFI_MODE_STA:
xTaskCreate(wifi_init_sta, "InitStationTask", 1024 * 4, (void*) 0, 3, NULL);
break;
xTaskCreate(wifi_init_sta, "InitStationTask", 1024 * 4, (void *)0, 3, NULL);
break;
case WIFI_MODE_AP:
xTaskCreate(wifi_init_softap, "InitSoftAPTask", 1024 * 4, (void*) 0, 3, NULL);
break;
xTaskCreate(wifi_init_softap, "InitSoftAPTask", 1024 * 4, (void *)0, 3, NULL);
break;
case WIFI_MODE_APSTA:
xTaskCreate(wifi_init_apsta, "InitSoftAPSTATask", 1024 * 4, (void*) 0, 3, NULL);
break;
xTaskCreate(wifi_init_apsta, "InitSoftAPSTATask", 1024 * 4, (void *)0, 3, NULL);
break;
}
isWiFiRunning = true;
//WiFi in work service
// WiFi in work service
TempAPCounter = GetSysConf()->wifiSettings.AP_disab_time * 60;
while (isWiFiRunning)
{
vTaskDelay(pdMS_TO_TICKS(1000));
if (isWiFiConnected)
{
reconnect_counter = RECONNECT_INTERVAL;
attempts = 0;
reconnect_counter = RECONNECT_INTERVAL_STA;
if (!isWiFiGotIp)
{
if (--waitip_counter <= 0)
@ -525,20 +496,25 @@ static void WiFiControlTask(void *arg)
}
}
if (isWiFiFail)
{
if (--reconnect_counter <= 0 && !isScanExecuting)
{
ESP_LOGI(TAG, "WiFi STA started, reconnecting to AP...");
esp_wifi_connect();
reconnect_counter = RECONNECT_INTERVAL;
if (++attempts <= RECONNECT_FAST_ATTEMPTS)
reconnect_counter = 5;
else
reconnect_counter = (GetSysConf()->wifiSettings.WiFiMode == WIFI_MODE_STA) ? RECONNECT_INTERVAL_STA : RECONNECT_INTERVAL_AP;
}
}
if (TempAPCounter > 0)
{
if (--TempAPCounter <= 0)
{
if (GetAPClientsNumber() > 0)
TempAPCounter = WIFI_AP_ONBOOT_TIME;
TempAPCounter = GetSysConf()->wifiSettings.AP_disab_time * 60;
else
{
WiFiStopAP();
@ -546,7 +522,6 @@ static void WiFiControlTask(void *arg)
}
}
}
}
if (isWiFiConnected)
@ -561,7 +536,7 @@ static void WiFiControlTask(void *arg)
void WiFiStart(void)
{
xTaskCreate(WiFiControlTask, "WiFiCtrlTask", 1024 * 4, (void*) 0, 3, NULL);
xTaskCreate(WiFiControlTask, "WiFiCtrlTask", 1024 * 4, (void *)0, 3, NULL);
}
void WiFiStop()
@ -597,11 +572,11 @@ static void wifi_scan(void *arg)
{
uint16_t number = DEFAULT_SCAN_LIST_SIZE;
uint16_t ap_count = 0;
vTaskDelay(pdMS_TO_TICKS(2000)); //delay for command result get before network break
vTaskDelay(pdMS_TO_TICKS(1000)); // delay for command result get before network break
memset(ap_info, 0, sizeof(ap_info));
while (esp_wifi_scan_start(NULL, true) == ESP_ERR_WIFI_STATE)
{
vTaskDelay(pdMS_TO_TICKS(2000));
vTaskDelay(pdMS_TO_TICKS(1000));
}
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
@ -614,7 +589,7 @@ static void wifi_scan(void *arg)
void WiFiScan(void)
{
isScanExecuting = true;
xTaskCreate(wifi_scan, "ScanWiFiTask", 1024 * 4, (void*) 0, 3, NULL);
xTaskCreate(wifi_scan, "ScanWiFiTask", 1024 * 4, (void *)0, 3, NULL);
}
int GetAPClientsNumber()
@ -630,4 +605,3 @@ int GetAPClientsNumber()
}
return -1;
}

119
src/sdcard.c Normal file
View 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

View File

@ -1,8 +1,5 @@
<table class="fixed" border="0">
<col width="700px" /><col width="500px" />
<table class="files" border="0">
<tr><td>
<h4>ESP32 File Server</h4>
</td><td>
<table border="0">
<tr>
<td>
@ -38,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 = 200*1024;
var MAX_FILE_SIZE_STR = "200KB";
var MAX_FILE_SIZE = 100*1000*1024;
var MAX_FILE_SIZE_STR = "100MB";
if (fileInput.length == 0) {
alert("No file selected!");
@ -49,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 > 200*1024) {
alert("File size must be less than 200KB!");
} 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;