添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
set(COMPONENT_SRCS "main.c"
"button.c"
"common.c"
"device_temp.c"
"i2c_temp.c"
"led.c"
"lwip_sntp.c"
"mqtt.c"
"nvs_storage.c"
"smart_config.c"
"wifi.c"
"http_server.c"
# "mqtt_ssl.c"
"native_ota.c"
# "https_ota.c"
# "statistic_free_rtos.c"
# "statistic_perfmon.c"
# "flash_encrypt.c"
)
set(COMPONENT_ADD_INCLUDEDIRS ". include")
set(COMPONENT_EMBED_TXTFILES ${project_dir}/server_certs/ca_cert.pem)
set(COMPONENT_EMBED_FILES "www/home.html.gz" "www/prompt.html.gz" "favicon.ico" "www/upload_script.html" "spiffs/test.pem" "main/spiffs/test.pem")
register_component()

View File

@@ -0,0 +1,65 @@
menu "Configuration"
config MAX_CPU_FREQ_MHZ
int "Maximum CPU frequency"
default 80
help
Maximum CPU frequency 80/160/240.
config MIN_CPU_FREQ_MHZ
int "Minimum CPU frequency"
default 10
help
Minimum CPU frequency 10/13/20/26/40.
choice SNTP_TIME_SYNC_METHOD
prompt "Time synchronization method"
default SNTP_TIME_SYNC_METHOD_IMMED
help
Time synchronization method.
config SNTP_TIME_SYNC_METHOD_IMMED
bool "update time immediately when received"
config SNTP_TIME_SYNC_METHOD_SMOOTH
bool "update time with smooth method (adjtime)"
config SNTP_TIME_SYNC_METHOD_CUSTOM
bool "custom implementation"
endchoice
config FIRMWARE_UPG_URL
string "Firmware Upgrade URL"
default "http://wumei.live/prod-api/common/download/firmware?fileName=wumei-open.bin"
help
URL of server which hosts the firmware image.
config SKIP_COMMON_NAME_CHECK
bool "Skip server certificate CN fieldcheck"
default n
help
This allows you to skip the validation of OTA server certificate CN field.
config SKIP_VERSION_CHECK
bool "Skip firmware version check"
default y
help
This allows you to skip the firmware version check.
config GPIO_DIAGNOSTIC
int "Number of the GPIO input for diagnostic"
range 0 39
default 35
help
Used to demonstrate how a rollback works.
The selected GPIO will be configured as an input with internal pull-up enabled.
To trigger a rollback, this GPIO must be pulled low while the message
`Diagnostics (5 sec)...` which will be on first boot.
If GPIO is not pulled low then the operable of the app will be confirmed.
config OTA_RECV_TIMEOUT
int "OTA Receive Timeout"
default 5000
help
Maximum time for reception
endmenu

View File

@@ -0,0 +1,337 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "button.h"
#include "common.h"
#include "smart_config.h"
#include "led.h"
#include "wifi.h"
#include "http_server.h"
#include "native_ota.h"
#include "mqtt.h"
#include "lwip_sntp.h"
#include "nvs_storage.h"
static const char* TAG = "button";
bool is_open=false;
//单击开关按钮(回调函数)
static void button_single_click_cb(void* arg)
{
ESP_EARLY_LOGI(TAG, "tab switch button\n");
if(relay_status==1)
{
close_relay();
relay_status=0;
}else{
open_relay();
relay_status=1;
}
write_relay_status();
// mqtt发布状态
if(is_wifi_offline==0 && wifi_status==1 ){
publishStatus();
}
}
//长按开关按钮
static void button_long_press_start_cb(void* arg)
{
ESP_LOGI(TAG, "begin smargconfig\n");
//蓝灯闪烁
led_rgb_blink(0,0,255,2,0,0,0,0);
//智能配网
smart_config_start();
}
// 连续短按开关按钮
static void button_press_repeat_cb(void *arg)
{
ESP_LOGI(TAG, "BUTTON_PRESS_REPEAT[%d]", iot_button_get_repeat((button_handle_t)arg));
uint8_t num=iot_button_get_repeat((button_handle_t)arg);
ESP_LOGI(TAG, "press repeat num: %d\n",num);
switch (num)
{
case 7:
ESP_LOGI(TAG, "native ota...\n");
led_rgb_blink(255,0,0,2,0,0,0,0);
native_ota_start();
break;
case 6:
//打开/关闭雷达
led_rgb_blink(0,0,255,2,0,6,0,0);
is_radar=is_radar==1 ? 0:1;
write_is_radar();
break;
case 5:
//遥控清码
ESP_LOGI(TAG, "rf clear code ...\n");
led_rgb_blink(0,0,255,2,0,5,0,0);
is_rf_clear=1;
rf_clear_code();
break;
case 4:
//遥控学习
ESP_LOGI(TAG, "rf learning... \n");
led_rgb_blink(0,0,255,2,0,4,0,0);
is_rf_learn=1;
rf_learn();
break;
case 3:
if(is_ap!=1){
// 打开ap
ESP_LOGI(TAG, "open access point \n");
is_ap=1;
ap_start();
}else{
//重启
device_restart();
}
break;
case 2:
ESP_EARLY_LOGI(TAG, "switch light \n");
light_status=light_status==0?1:0;
led_status();
write_light_status();
break;
default:
break;
}
// mqtt发布状态
if(is_wifi_offline==0 && wifi_status==1 ){
publishSetting();
publishStatus();
}
}
void button_start()
{
printf("before btn init, heap: %d\n", esp_get_free_heap_size());
//初始化继电器引脚
gpio_pad_select_gpio(IO_RELAY);
gpio_set_direction(IO_RELAY,GPIO_MODE_OUTPUT);
//初始化按键
button_config_t cfg = {
.type = BUTTON_TYPE_GPIO,
.gpio_button_config = {
.gpio_num = IO_SWITCH_BUTTON,
.active_level = 0,
},
};
button_handle_t gpio_btn = iot_button_create(&cfg);
if(NULL == gpio_btn) { ESP_LOGE(TAG, "Button create failed"); }
iot_button_register_cb(gpio_btn, BUTTON_SINGLE_CLICK, button_single_click_cb); //短按
iot_button_register_cb(gpio_btn, BUTTON_LONG_PRESS_START, button_long_press_start_cb); //长按
iot_button_register_cb(gpio_btn, BUTTON_PRESS_REPEAT, button_press_repeat_cb); //连续短按
}
/************************************* begin RF接收信号 ***************************************/
static void process_rf_func(uint8_t function){
if(function==1){
//打开关闭继电器
ESP_LOGI(TAG, "switch relay\n");
if(relay_status==0){
open_relay();
relay_status=1;
}else if(relay_status==1){
close_relay();
relay_status=0;
}
write_relay_status();
}else if(function==2){
//打开关闭灯
ESP_LOGI(TAG, "switch light\n");
light_status=light_status==0?1:0;
led_status();
}else if(function==3){
//打开关闭雷达
ESP_LOGI(TAG, "switch radar\n");
if(is_radar==0){
is_radar=1;
}else if(is_radar==1){
is_radar=0;
}
write_is_radar();
}else if(function==4){
//打开关闭报警
ESP_LOGI(TAG, "switch alarm\n");
if(is_alarm==0){
is_alarm=1;
}else if(is_alarm==1){
is_alarm=0;
}
write_is_alarm();
}else if(function==5){
ESP_LOGI(TAG, "smart config\n");
if(is_smart_config==0){
ESP_LOGI(TAG, "begin smargconfig\n");
// wifi_mqtt_stop();
is_smart_config=1;
//蓝灯闪烁
// led_rgb_blink(0,0,255,2,0,0,0,0);
//智能配网
smart_config_start();
}else{
is_smart_config=0;
ESP_LOGI(TAG, "device restart\n");
device_restart();
}
}
// mqtt发布状态
if(is_wifi_offline==0 && wifi_status==1 ){
publishStatus();
publishSetting();
}
}
//RF接收任务
static void rf_receiver_task(void *arg) {
ESP_LOGI(TAG, "begin rf receiver");
// uint32_t gpio_num = (uint32_t) arg;
while(true)
{
if(gpio_get_level(IO_RF_RECEIVER_A)==1)
{
process_rf_func(rf_one_func);
}else if(gpio_get_level(IO_RF_RECEIVER_B)==1)
{
process_rf_func(rf_two_func);
}else if(gpio_get_level(IO_RF_RECEIVER_C)==1)
{
process_rf_func(rf_three_func);
}else if(gpio_get_level(IO_RF_RECEIVER_D)==1)
{
process_rf_func(rf_four_func);
}
vTaskDelay(pdMS_TO_TICKS(250));
}
}
void rf_receiver_start(void)
{
// 初始化射频引脚
gpio_pad_select_gpio(IO_RF_RECEIVER_D);
gpio_pad_select_gpio(IO_RF_RECEIVER_C);
gpio_pad_select_gpio(IO_RF_RECEIVER_B);
gpio_pad_select_gpio(IO_RF_RECEIVER_A);
gpio_pad_select_gpio(IO_RF_LEARN_KEY);
gpio_set_direction(IO_RF_RECEIVER_D,GPIO_MODE_INPUT);
gpio_set_direction(IO_RF_RECEIVER_C,GPIO_MODE_INPUT);
gpio_set_direction(IO_RF_RECEIVER_B,GPIO_MODE_INPUT);
gpio_set_direction(IO_RF_RECEIVER_A,GPIO_MODE_INPUT);
gpio_set_direction(IO_RF_LEARN_KEY,GPIO_MODE_OUTPUT);
// gpio_set_pull_mode(IO_RF_RECEIVER_D,GPIO_PULLDOWN_ONLY);
// gpio_set_pull_mode(IO_RF_RECEIVER_C,GPIO_PULLDOWN_ONLY);
// gpio_set_pull_mode(IO_RF_RECEIVER_B,GPIO_PULLDOWN_ONLY);
// gpio_set_pull_mode(IO_RF_RECEIVER_A,GPIO_PULLDOWN_ONLY);
//创建接收信号任务
xTaskCreate(rf_receiver_task, "rf_receiver_task", 2048, (void*) IO_RF_RECEIVER_A, 10, NULL);
}
/************************************* end RF接信号 ***************************************/
/************************************* begin 雷达感应 ***************************************/
//雷达感应任务
static void radar_sense(void *arg) {
ESP_LOGI(TAG, "begin radar sense");
uint16_t num=0;
while(true){
// if(is_radar==1 && is_alarm==1){
// if(gpio_get_level(IO_RADAR_OUT)==1){
// if(relay_status==0) {
// open_relay();
// led_rgb_blink(255,0,0,100,0,0,3,1000); //红灯闪烁
// }
// }
// else{
// //超过指定时间后关闭
// if(relay_status==1 && num >5*radar_interval){
// close_relay();
// light_status=0;
// led_status();
// num=0;
// }
// num++;
// }
// } else if(is_radar==1) {
// if(gpio_get_level(IO_RADAR_OUT)==1){
// if(relay_status==0) {
// open_relay();
// light_status=1;
// led_status();
// }
// }
// else{
// //超过指定时间后关闭
// if(relay_status==1 && num >5*radar_interval){
// close_relay();
// light_status=0;
// led_status();
// num=0;
// }
// num++;
// }
// }
vTaskDelay(pdMS_TO_TICKS(200));
}
}
// void radar_cds_enable(void){
// gpio_set_level(IO_RADAR_CDS,1);
// }
// void radar_cds_disable(void){
// gpio_set_level(IO_RADAR_CDS,0);
// }
void radar_start(void){
// 初始化射频引脚
gpio_pad_select_gpio(IO_RADAR_OUT);
gpio_set_direction(IO_RADAR_OUT,GPIO_MODE_INPUT);
gpio_set_pull_mode(IO_RADAR_OUT, GPIO_PULLDOWN_ONLY);
// gpio_pad_select_gpio(IO_RADAR_CDS);
// gpio_set_direction(IO_RADAR_CDS,GPIO_MODE_INPUT_OUTPUT);
// gpio_set_pull_mode(IO_RADAR_OUT, GPIO_PULLUP_ONLY);
xTaskCreate(radar_sense,"radar_sense", 2048,NULL,10,NULL);
}
/************************************* end 雷达感应 ***************************************/

View File

@@ -0,0 +1,61 @@
-----BEGIN CERTIFICATE-----
MIIFozCCBIugAwIBAgIQAYsnZvaMC5bMX7h0TswAKTANBgkqhkiG9w0BAQsFADBy
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg
SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy
dXN0QXNpYSBUTFMgUlNBIENBMB4XDTIwMTIyMTAwMDAwMFoXDTIxMTIyMDIzNTk1
OVowFTETMBEGA1UEAxMKd3VtZWkubGl2ZTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAI8h79x+bD06Mg06hkC5ECJCeUXeSz4YeKJCfoc4RBYweynzMnTn
9ntJhjmAfd5QnO4GsoGUQ9Znwvw/hkuztzU6+TvPTVXPG3Lv8i0raXkbiqm0z1/H
eBMAXcQF+PjKxkPZC+pxCGchhaTiTV13eiazrhPlJdfC94jlAcQclgk2T7K4ZrtL
h3rG1qzD09YPf+DEHR//1gSC0KWS37cZF7aT2SkNWHQtjTd/+8R5uCweUCCzwATO
afNmb4k7m8vvtiiTs15VwzxHEF1ieFoU/BuuzAJeu1AmeVc1bzfXfM/rJM/5Ay4a
Nas2oD0vG77Br933UjUpMz3CwSOjXB0dVccCAwEAAaOCApAwggKMMB8GA1UdIwQY
MBaAFH/TmfOgRw4xAFZWIo63zJ7dygGKMB0GA1UdDgQWBBSVm9OdffCIXlvduPV2
r18Zlh9tcDAlBgNVHREEHjAcggp3dW1laS5saXZlgg53d3cud3VtZWkubGl2ZTAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEwG
A1UdIARFMEMwNwYJYIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIBMIGSBggrBgEFBQcBAQSBhTCBgjA0
BggrBgEFBQcwAYYoaHR0cDovL3N0YXR1c2UuZGlnaXRhbGNlcnR2YWxpZGF0aW9u
LmNvbTBKBggrBgEFBQcwAoY+aHR0cDovL2NhY2VydHMuZGlnaXRhbGNlcnR2YWxp
ZGF0aW9uLmNvbS9UcnVzdEFzaWFUTFNSU0FDQS5jcnQwCQYDVR0TBAIwADCCAQQG
CisGAQQB1nkCBAIEgfUEgfIA8AB1APZclC/RdzAiFFQYCDCUVo7jTRMZM7/fDC8g
C8xO8WTjAAABdoXFWi0AAAQDAEYwRAIgAN5rK3xcFR6TtHb/RkqcQjO2YYgYOKsc
HbMDltyHeK4CIAMhOhT2eq/acUrUaqRPxhgOHxgHUzGSQX3zKNfRauHAAHcAXNxD
kv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDsoAAAF2hcVadQAABAMASDBGAiEA
v2MQwoTsZdVqEvy0nY7WqyKYzBqtCAbggf7sqCrjUBgCIQC9tkuME/dx5AwU/Mbi
wNEx1ynW76Qo4AqxTurCaumRAzANBgkqhkiG9w0BAQsFAAOCAQEAjyiB/sgUC2Oo
lUvFvm4H1RyaqHLnPQP56yq/jCPerJl4hBdJd7BEIioAGSlEv+ttOFgcgcUHd2Y9
uiTgRnjCEQqWcVmn8Doj+dtJYplwgBUVQgMWyWcnVuPTiVYpgPR9+yA6YADhfbF9
8xXpQ9SYgAXdgl/F9VFRsxS8Pf0Mh3wokvrSRgRHfeGa4bNKPDssQ/3j2KpdAHt8
PMQ82+Aph9g69zdC/aRILAZK9Iduwfdo4uHCx23NhfSzAEcpg/JOgldzyK10H+nF
E91UK1KKrCKuvpoAUUhDPTXQCQPhq0ZBfdD3IqMZXjiKL4hxXdA4InJDIk31WCrm
43vLujdduA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO
MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL
ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS
U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8
Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa
e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO
JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA
zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK
ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe
3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K
AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD
AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG
AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj
ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg
hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t
L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233
lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ
DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP
ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F
UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C
qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY
RmE=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAjyHv3H5sPToyDTqGQLkQIkJ5Rd5LPhh4okJ+hzhEFjB7KfMy
dOf2e0mGOYB93lCc7gaygZRD1mfC/D+GS7O3NTr5O89NVc8bcu/yLStpeRuKqbTP
X8d4EwBdxAX4+MrGQ9kL6nEIZyGFpOJNXXd6JrOuE+Ul18L3iOUBxByWCTZPsrhm
u0uHesbWrMPT1g9/4MQdH//WBILQpZLftxkXtpPZKQ1YdC2NN3/7xHm4LB5QILPA
BM5p82ZviTuby++2KJOzXlXDPEcQXWJ4WhT8G67MAl67UCZ5VzVvN9d8z+skz/kD
Lho1qzagPS8bvsGv3fdSNSkzPcLBI6NcHR1VxwIDAQABAoIBADrPhu7iQzclIkut
MFyHrcll5s5+eAwbofWJvNNymwdDBFhIRQMkDHK70xrtYMpn9RMYTWBQu07tc4CR
2Wxhe3WztZSNqQkJAA5J6QgGPmA0oNT6JfsEyqGEFQLmMVaIes6F8A90Qi+d5nvJ
QGCXJumgCnbCQLpWsb7d2cvqsvs1aDlsjGcgK/oyA7JRhTsTow6tTVH/mSWCKuzg
NPqNk9I+sYKFJP8ra2uy3773IW6fZPTOZ4nAKLIfwJJj2WJwzgKM3ng/wLhkNQDj
Cc3teOKu0lcoCcxPE/9SfOs0quE7E5+rdRyCbnnhno+BGkIWuMNIBp/tt7Yd/iID
k7As/gECgYEAx3shKufAJz67vmmC6UR6Ai4RRtQlpD5BKbQAS5O5aHl5LMWFXqF1
b+HpWETusnt7Hv4I5ZiDyqA6bBFk9xLt+l41PC2xnJqk1hqqgNCZ4nni8kSXvTT6
JW9qHqv4HBNgHBnoEnkqNtPz+idTqorHTqehQMx3r5a3F4q3djn4yTcCgYEAt6+2
NWcfgDsmV6au+L9I2Hw9cl37jXKkEA9uqcma3tnAvbe8iMPO+3+WOcPGV1Fov3hF
4yr2on9a/V0Gcimfd3YmLOl4j/c5cvLv127K5Itc6kOv3OetAmPaj7GUomRDWCmG
oJ8dODicAkDBVrSnOZGYJDHkjOUNS5f+GM7n3/ECgYEAkQAJrfxjiqNpKRHdHN6v
qWH/IPMYoXi3OS8kf8tTnIOf91FkjtLiYH9gdM82ivqDFpYltW7VbbZmgSNrtsVF
wxYzsBiu4FzwsMkVYyk+kody1hPSELCvnAKOqtjqMs5KsGKMdNEqRExxLkbj5DWY
hq4G4uk9np75W91zWjbthqUCgYA/xk/65pz3RpIfaI3ja3Z9Q1WKObs29xCjSthf
NtIAgZX7yKk6ytE4XKnp0GEyu98kazvIjYgoDxOmV//+7xigv3KtsTncsjdOA67m
G19yTjiqVWnfxsg4xjaCIWO7phgDqhdF+TiJ5o2z8out8PcGc9hg6LmzeWtOTa05
K80x4QKBgFM7pXYpPeYjhSIjY0YH2sT/hSva9u92bisph14FCakF4z7RDpybZzrq
B6ZktMV2WVyuxQTX+kcudghS9asDOfNf2fVhbtEfD5DzWVi75n6gQNqh+oL5ibbQ
sYRTqUf808Zns0bMUgD6XNt8qTv1XNywU0364BZ3V1OISb1waqoA
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,245 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "common.h"
#include "smart_config.h"
#include "led.h"
#include "wifi.h"
#include "mqtt.h"
#include "nvs_storage.h"
#include "driver/temp_sensor.h"
char ssid[33]="tp-six"; // wifi的SSID
char pwd[65]="clh15108665817"; // wifi的密码
char owner_id[64]="1"; // 用户ID
char open_broken_url[128]=""; // 二次开发mqtt服务器地址
char open_account[64]=""; // 二次开发mqtt账号
char open_pwd[64]=""; // 二次开发mqtt密码
uint8_t relay_status=0; // 继电器状态 0-关闭1-打开
uint8_t light_status=0; // 灯的状态 0-关闭 1-打开
uint8_t light_mode=0; // 颜色模式 0-固定颜色 1-七彩渐变 2-七彩动感 3-单色渐变 4-白光 5-暖光
uint8_t is_radar=0; // 是否进入雷达感应
uint8_t is_alarm=0; // 是否打开报警
uint8_t is_wifi_offline=0; // 是否离线模式
uint8_t is_open_certifi=0; // 二次开发是否使用证书
uint8_t is_host=1; // 是否托管
uint8_t is_rf_control=1; // 是否使用RF遥控
uint8_t rf_one_func=1; // 第一个遥控按键功能1-继电器通断2-开关灯开关雷达4-报警开关5-智能配网
uint8_t rf_two_func=2; // 第二个遥控按键功能
uint8_t rf_three_func=3; // 第三个遥控按键功能
uint8_t rf_four_func=4; // 第四个遥控按键功能
uint32_t red=255; // 红色值 0-255
uint32_t gree=255; // 绿色值
uint32_t blue=0; // 蓝色值
uint32_t brightness=100; // 亮度0-100
uint32_t light_interval=1000; // 颜色闪烁间隔
uint32_t radar_interval=5; // 雷达开灯持续时间,单位秒
uint32_t fade_time=100; // 灯渐变时间
// 全局变量-不需要存储
char device_num[13]=""; // 设备编号mac地址
int8_t rssi=-100; // wifi信号强度(信号极好4格[-55—— 0]信号好3格[-70—— -55]信号一般2格[-85—— -70]信号差1格[-100—— -85])
uint8_t wifi_status=0; // wifi连接状态0-未联网1-已联网
uint8_t trigger_source=0; // 触发源0-无、1-按键、2.手机、3-浏览器、4-射频遥控、5-雷达、6-报警、7-定时
uint8_t is_reset=0; // 是否重启
uint8_t is_ap=0; // 是否打开AP
uint8_t is_rf_learn=0; // 遥控配对
uint8_t is_rf_clear=0; // 遥控清码
uint8_t is_smart_config=0; // 智能配网
float device_temp=0; // 设备温度
float air_temperature=0; // 空气温度
float air_humidity=0; // 空气湿度
static const char* TAG = "common";
//关闭继电器
void close_relay(void)
{
ESP_LOGI(TAG, "close relay");
gpio_set_level(IO_RELAY, 0);
}
//打开继电器
void open_relay(void)
{
ESP_LOGI(TAG, "open relay");
gpio_set_level(IO_RELAY, 1);
}
//设备重启
void device_restart(void)
{
printf("Restarting now...\n");
mqtt_stop();
esp_wifi_stop();
fflush(stdout);
esp_restart();
}
// 获取AP中的rssi
void get_ap_info(void)
{
if(wifi_status==1){
//获取AP信息
wifi_ap_record_t ap_info;
esp_wifi_sta_get_ap_info(&ap_info);
ESP_LOGI(TAG,"ap signal:%4d\n",ap_info.rssi);
rssi=ap_info.rssi;
}else{
rssi=-110;
}
}
// -----------------------------------------------------------------
// 函数功能: 字节数组转字符串类型
// 函数名称: hexbyte_to_hex_str
// 参数1 : src 源字符串
// 参数2 : obj 目标字节数组
// 说明 : {0x01,0x03,0x03,x04} --> "01020304"
// 返回值 : 1 成功
// -----------------------------------------------------------------
static int hexbyte_to_hex_str (uint8_t *src, char *obj, uint16_t length)
{
for (int i = 0; i < length; i++)
{
sprintf (obj, "%02X", src[i]);
obj += 2;
}
return 1;
}
//获取设备mac地址
void get_device_num(void)
{
uint8_t base_mac_addr[6] = {0};
esp_err_t ret = ESP_OK;
ret=esp_efuse_mac_get_default(base_mac_addr); //获取工厂编程的基本MAC这是唯一的
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK0. (%s)", esp_err_to_name(ret));
ESP_LOGE(TAG, "Aborting");
abort();
} else {
ESP_LOGI(TAG, "Base MAC Address read from EFUSE BLK0");
}
//获取基本mac地址
ESP_LOGI(TAG, "Using \"0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\" as base MAC address",
base_mac_addr[0], base_mac_addr[1], base_mac_addr[2], base_mac_addr[3], base_mac_addr[4], base_mac_addr[5]);
hexbyte_to_hex_str(base_mac_addr,device_num,sizeof(base_mac_addr));
device_num[12]='\0';
ESP_LOGI(TAG,"mac address:%s",device_num);
}
//读取spiffs中的证书
void read_cert(void)
{
ESP_LOGI(TAG, "Initializing SPIFFS");
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = true
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info(conf.partition_label, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
} else {
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
// Open renamed file for reading
ESP_LOGI(TAG, "Reading file");
FILE* f = fopen("/spiffs/ca_cert.pem", "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[256]={0};
char all_line[2048] ={0};
printf("sizeof:%d\n",sizeof(line));
while(fgets(line, sizeof(all_line), f)!=NULL){
strcat(all_line,line);
printf("Read from file: '%s'", line);
}
fclose(f);
// All done, unmount partition and disable SPIFFS
esp_vfs_spiffs_unregister(conf.partition_label);
ESP_LOGI(TAG, "SPIFFS unmounted");
}
//设备温度初始化
void device_temp_init(void){
// 初始化触摸板外围设备,它将启动计时器以运行过滤器
ESP_LOGI(TAG, "Initializing Temperature sensor");
temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
temp_sensor_get_config(&temp_sensor);
ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);
temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // 默认: 范围:-10℃ ~ 80℃, 错误 < 1℃.
temp_sensor_set_config(temp_sensor);
temp_sensor_start();
ESP_LOGI(TAG, "Temperature sensor started");
temp_sensor_read_celsius(&device_temp);
ESP_LOGI(TAG, "Temperature out celsius %f°C", device_temp);
}
// 433接收模块清码
void rf_clear_code(void){
for(int i=0;i<8;i++)
{
gpio_set_level(IO_RF_LEARN_KEY,1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(IO_RF_LEARN_KEY,0);
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// 433接收模块对码
void rf_learn(void){
gpio_set_level(IO_RF_LEARN_KEY,1);
vTaskDelay(pdMS_TO_TICKS(100));
gpio_set_level(IO_RF_LEARN_KEY,0);
}

View File

@@ -0,0 +1,7 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/server_certs/ca_cert.pem

View File

@@ -0,0 +1,38 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "device_temp.h"
static const char *TAG = "TempSensor";
static void tempsensor_task(void *arg)
{
// 初始化触摸板外围设备,它将启动计时器以运行过滤器
ESP_LOGI(TAG, "Initializing Temperature sensor");
float tsens_out;
temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
temp_sensor_get_config(&temp_sensor);
ESP_LOGI(TAG, "default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);
temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // 默认: 范围:-10℃ ~ 80℃, 错误 < 1℃.
temp_sensor_set_config(temp_sensor);
temp_sensor_start();
ESP_LOGI(TAG, "Temperature sensor started");
while (1) {
vTaskDelay(1000 / portTICK_RATE_MS);
temp_sensor_read_celsius(&tsens_out);
ESP_LOGI(TAG, "Temperature out celsius %f°C", tsens_out);
}
vTaskDelete(NULL);
}
void get_device_temp(void)
{
xTaskCreate(tempsensor_task, "temp", 2048, NULL, 5, NULL);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,89 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "flash_encrypt.h"
static void print_chip_info(void);
static void print_flash_encryption_status(void);
static void read_write_flash(void);
static const char* TAG = "flash-encrypt";
void flash_encrypy_start(void)
{
printf("\ncheck Flash Encryption status\n");
print_chip_info();
print_flash_encryption_status();
read_write_flash();
}
static void print_chip_info(void)
{
/* 打印芯片信息 */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
printf("silicon revision %d, ", chip_info.revision);
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
}
static void print_flash_encryption_status(void)
{
uint32_t flash_crypt_cnt = 0;
esp_efuse_read_field_blob(TARGET_CRYPT_CNT_EFUSE, &flash_crypt_cnt, TARGET_CRYPT_CNT_WIDTH);
printf("FLASH_CRYPT_CNT eFuse value is %d\n", flash_crypt_cnt);
esp_flash_enc_mode_t mode = esp_get_flash_encryption_mode();
if (mode == ESP_FLASH_ENC_MODE_DISABLED) {
printf("Flash encryption feature is disabled\n");
} else {
printf("Flash encryption feature is enabled in %s mode\n", mode == ESP_FLASH_ENC_MODE_DEVELOPMENT ? "DEVELOPMENT" : "RELEASE");
}
}
static void read_write_flash(void)
{
const esp_partition_t* partition = esp_partition_find_first(
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
assert(partition);
printf("Erasing partition \"%s\" (0x%x bytes)\n", partition->label, partition->size);
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
/*生成将要写入的数据 */
const size_t data_size = 32;
uint8_t plaintext_data[data_size];
for (uint8_t i = 0; i < data_size; ++i) {
plaintext_data[i] = i;
}
printf("Writing data with esp_partition_write:\n");
ESP_LOG_BUFFER_HEXDUMP(TAG, plaintext_data, data_size, ESP_LOG_INFO);
ESP_ERROR_CHECK(esp_partition_write(partition, 0, plaintext_data, data_size));
uint8_t read_data[data_size];
printf("Reading with esp_partition_read:\n");
ESP_ERROR_CHECK(esp_partition_read(partition, 0, read_data, data_size));
ESP_LOG_BUFFER_HEXDUMP(TAG, read_data, data_size, ESP_LOG_INFO);
printf("Reading with spi_flash_read:\n");
ESP_ERROR_CHECK(spi_flash_read(partition->address, read_data, data_size));
ESP_LOG_BUFFER_HEXDUMP(TAG, read_data, data_size, ESP_LOG_INFO);
}

View File

@@ -0,0 +1,702 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "http_server.h"
#include "esp_vfs.h"
#include "cJSON.h"
#include "common.h"
#include "nvs_storage.h"
#include <string.h>
#include "esp_vfs.h"
#include "esp_spiffs.h"
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include "esp_err.h"
#include "esp_log.h"
/* 文件路径在存储上的最大长度 */
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
/* 单个文件的最大值。确保这个值与upload_script.html中设置的值相同 */
#define MAX_FILE_SIZE (200*1024) // 200 KB
#define MAX_FILE_SIZE_STR "200KB"
/* 暂存缓冲区大小 */
#define SCRATCH_BUFSIZE 8192
struct file_server_data {
/* Base path of file storage */
char base_path[ESP_VFS_PATH_MAX + 1];
/* Scratch buffer for temporary storage during file transfer */
char scratch[SCRATCH_BUFSIZE];
};
static const char *TAG = "http-server";
static esp_err_t home_handler(httpd_req_t *req)
{
extern const unsigned char home_html_gz_start[] asm("_binary_home_html_gz_start");
extern const unsigned char home_html_gz_end[] asm("_binary_home_html_gz_end");
size_t home_html_gz_len = home_html_gz_end - home_html_gz_start;
httpd_resp_set_type(req, "text/html");
httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
return httpd_resp_send(req, (const char *)home_html_gz_start, home_html_gz_len);
}
static esp_err_t wifi_post_handler(httpd_req_t *req)
{
char buf[300];
int ret;
int total_len = req->content_len;
if (total_len >= 300) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
return ESP_FAIL;
}
while (total_len > 0) {
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf, MIN(total_len, sizeof(buf)))) <= 0) {
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
/* Retry receiving if timeout occurred */
continue;
}
return ESP_FAIL;
}
buf[total_len] = '\0';
total_len -= ret;
ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
ESP_LOGI(TAG, "%.*s", ret, buf);
// char ssid[64],password[64],uuid[100];
sscanf(buf, "ssid=%[^&]&password=%[^&]&uuid=%s",ssid,pwd,owner_id);
ESP_LOGI(TAG, "ssid:%s,password:%s,uuid:%s", ssid, pwd, owner_id);
//存储wifi信息
write_ssid();
write_pwd();
write_owner_id();
//响应
extern const unsigned char prompt_html_gz_start[] asm("_binary_prompt_html_gz_start");
extern const unsigned char prompt_html_gz_end[] asm("_binary_prompt_html_gz_end");
size_t prompt_html_gz_len = prompt_html_gz_end - prompt_html_gz_start;
httpd_resp_set_type(req, "text/html");
httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
return httpd_resp_send(req, (const char *)prompt_html_gz_start, prompt_html_gz_len);
}
return ESP_FAIL;
}
static esp_err_t mqtt_post_handler(httpd_req_t *req)
{
char buf[800];
int ret, total_len = req->content_len;
if (total_len >= 800) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
return ESP_FAIL;
}
while (total_len > 0) {
/* Read the data for the request */
if ((ret = httpd_req_recv(req, buf, MIN(total_len, sizeof(buf)))) <= 0) {
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
/* Retry receiving if timeout occurred */
continue;
}
return ESP_FAIL;
}
buf[total_len] = '\0';
total_len -= ret;
ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
ESP_LOGI(TAG, "%.*s", ret, buf);
char mqtt_port[32];
int value=0;
int *is_certifi=&value;
sscanf(buf, "mqtt_address=%[^&]&mqtt_port=%[^&]&mqtt_account=%[^&]&mqtt_password=%[^&]&is_certifi=%d",open_broken_url,mqtt_port,open_account,open_pwd,is_certifi);
is_open_certifi=*is_certifi;
ESP_LOGI(TAG, "mqtt_address:%s,mqtt_port:%s,mqtt_account:%s,mqtt_password:%s,is_open_certifi:%d", open_broken_url,mqtt_port, open_account, open_pwd,is_open_certifi);
//存储
is_host=1;
write_is_host();
write_open_account();
write_open_pwd();
write_is_open_certifi();
// 合并mqtt的地址
strcat(open_broken_url,":");
strcat(open_broken_url,mqtt_port);
printf("mqtt地址%s",open_broken_url);
write_open_broken_url();
extern const unsigned char prompt_html_gz_start[] asm("_binary_prompt_html_gz_start");
extern const unsigned char prompt_html_gz_end[] asm("_binary_prompt_html_gz_end");
size_t prompt_html_gz_len = prompt_html_gz_end - prompt_html_gz_start;
httpd_resp_set_type(req, "text/html");
httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
return httpd_resp_send(req, (const char *)prompt_html_gz_start, prompt_html_gz_len);
}
return ESP_FAIL;
}
/* 将传入的GET请求重定向到/index.html的处理程序可以通过上传同名文件来覆盖 */
static esp_err_t index_html_get_handler(httpd_req_t *req)
{
httpd_resp_set_status(req, "307 Temporary Redirect");
httpd_resp_set_hdr(req, "Location", "/download/");
httpd_resp_send(req, NULL, 0); // Response body can be empty
return ESP_OK;
}
/* 处理程序响应一个嵌入在flash中的图标文件。浏览器期望在URI /favicon.ico获得网站图标。可以通过上传同名文件来覆盖 */
static esp_err_t favicon_get_handler(httpd_req_t *req)
{
extern const unsigned char favicon_ico_start[] asm("_binary_favicon_ico_start");
extern const unsigned char favicon_ico_end[] asm("_binary_favicon_ico_end");
const size_t favicon_ico_size = (favicon_ico_end - favicon_ico_start);
httpd_resp_set_type(req, "image/x-icon");
httpd_resp_send(req, (const char *)favicon_ico_start, favicon_ico_size);
return ESP_OK;
}
/* 功 能将str字符串中的oldstr字符串替换为newstr字符串
* 参 数str操作目标 oldstr被替换者 newstr替换者
* 返回值:返回替换之后的字符串
*/
char *strrpc(char *str,char *oldstr,char *newstr){
char bstr[strlen(str)];//转换缓冲区
memset(bstr,0,sizeof(bstr));
for(int i = 0;i < strlen(str);i++){
if(!strncmp(str+i,oldstr,strlen(oldstr))){//查找目标字符串
strcat(bstr,newstr);
i += strlen(oldstr) - 1;
}else{
strncat(bstr,str + i,1);//保存一字节进缓冲区
}
}
strcpy(str,bstr);
return str;
}
/* 用运行时生成的html(包含请求路径下的所有文件和文件夹的列表)发送HTTP响应。在SPIFFS的情况下当path是除'/'以外的任何字符串时将返回空列表因为SPIFFS不支持目录 */
static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
{
char entrypath[FILE_PATH_MAX];
char entrysize[16];
const char *entrytype;
struct dirent *entry;
struct stat entry_stat;
DIR *dir = opendir(dirpath);
const size_t dirpath_len = strlen(dirpath);
/* Retrieve the base path of file storage to construct the full path */
strlcpy(entrypath, dirpath, sizeof(entrypath));
if (!dir) {
ESP_LOGE(TAG, "Failed to stat dir : %s", dirpath);
/* Respond with 404 Not Found */
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
return ESP_FAIL;
}
/* Send HTML file header */
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><meta charset=""utf-8""><meta name=""viewport"" content=""width=device-width,initial-scale=1""><title>物美智能设备AP配置</title><body>");
/* Get handle to embedded file upload script */
extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
extern const unsigned char upload_script_end[] asm("_binary_upload_script_html_end");
const size_t upload_script_size = (upload_script_end - upload_script_start);
/* Add file upload form and script which on execution sends a POST request to /upload */
httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);
/* Send file-list table definition and column labels */
httpd_resp_sendstr_chunk(req,
"<div id=""list""><table>"
"<thead><tr><td>名称</td><td>类型</td><td>字节</td><td>操作</td></tr></thead>"
"<tbody>");
/* Iterate over all files / folders and fetch their names and sizes */
while ((entry = readdir(dir)) != NULL) {
entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
if (stat(entrypath, &entry_stat) == -1) {
ESP_LOGE(TAG, "Failed to stat %s : %s", entrytype, entry->d_name);
continue;
}
sprintf(entrysize, "%ld", entry_stat.st_size);
ESP_LOGI(TAG, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
/* 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, "<tr><td>");
// httpd_resp_sendstr_chunk(req, req->uri);
// httpd_resp_sendstr_chunk(req, entry->d_name);
// if (entry->d_type == DT_DIR) {
// httpd_resp_sendstr_chunk(req, "/");
// }
// httpd_resp_sendstr_chunk(req, "\">");
httpd_resp_sendstr_chunk(req, entry->d_name);
httpd_resp_sendstr_chunk(req, "</td><td>");
// httpd_resp_sendstr_chunk(req, "</a></td><td>");
httpd_resp_sendstr_chunk(req, entrytype);
httpd_resp_sendstr_chunk(req, "</td><td>");
httpd_resp_sendstr_chunk(req, entrysize);
httpd_resp_sendstr_chunk(req, "</td><td>");
httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
httpd_resp_sendstr_chunk(req, req->uri);
httpd_resp_sendstr_chunk(req, entry->d_name);
httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">删除</button></form>");
httpd_resp_sendstr_chunk(req, "</td></tr>\n");
}
closedir(dir);
/* Finish the file list table */
httpd_resp_sendstr_chunk(req, "</tbody></table><div>");
/* Send remaining chunk of HTML file to complete it */
httpd_resp_sendstr_chunk(req, "</body></html>");
/* Send empty chunk to signal HTTP response completion */
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
#define IS_FILE_EXT(filename, ext) \
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
/* 根据文件扩展设置HTTP响应内容类型 */
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename)
{
if (IS_FILE_EXT(filename, ".pdf")) {
return httpd_resp_set_type(req, "application/pdf");
} else if (IS_FILE_EXT(filename, ".html")) {
return httpd_resp_set_type(req, "text/html");
} else if (IS_FILE_EXT(filename, ".jpeg")) {
return httpd_resp_set_type(req, "image/jpeg");
} else if (IS_FILE_EXT(filename, ".ico")) {
return httpd_resp_set_type(req, "image/x-icon");
} else if (IS_FILE_EXT(filename, ".crt")) {
return httpd_resp_set_type(req, "application/x-x509-ca-cert");
}
/* This is a limited set only */
/* For any other type always set as plain text */
return httpd_resp_set_type(req, "text/plain");
}
/*将完整路径复制到目标缓冲区并返回指向路径的指针(跳过前面的基路径) */
static const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize)
{
const size_t base_pathlen = strlen(base_path);
size_t pathlen = strlen(uri);
const char *quest = strchr(uri, '?');
if (quest) {
pathlen = MIN(pathlen, quest - uri);
}
const char *hash = strchr(uri, '#');
if (hash) {
pathlen = MIN(pathlen, hash - uri);
}
if (base_pathlen + pathlen + 1 > destsize) {
/* Full path string won't fit into destination buffer */
return NULL;
}
/* Construct full path (base + path) */
strcpy(dest, base_path);
strlcpy(dest + base_pathlen, uri, pathlen + 1);
//删除路径中的download字符串
strrpc(dest,"/download","");
/* Return pointer to path, skipping the base */
return dest + base_pathlen;
}
/* 下载服务器里面的文件 */
static esp_err_t download_get_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
FILE *fd = NULL;
struct stat file_stat;
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
req->uri, sizeof(filepath));
if (!filename) {
ESP_LOGE(TAG, "Filename is too long");
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
return ESP_FAIL;
}
/* If name has trailing '/', respond with directory contents */
if (filename[strlen(filename) - 1] == '/') {
return http_resp_dir_html(req, filepath);
}
if (stat(filepath, &file_stat) == -1) {
/* If file not present on SPIFFS check if URI
* corresponds to one of the hardcoded paths */
if (strcmp(filename, "/index.html") == 0) {
return index_html_get_handler(req);
} else if (strcmp(filename, "/favicon.ico") == 0) {
return favicon_get_handler(req);
}
ESP_LOGE(TAG, "Failed to stat file : %s", filepath);
/* Respond with 404 Not Found */
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
return ESP_FAIL;
}
fd = fopen(filepath, "r");
if (!fd) {
ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
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;
size_t chunksize;
do {
/* Read file in chunks into the scratch buffer */
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
if (chunksize > 0) {
/* Send the buffer contents as HTTP response chunk */
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
fclose(fd);
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;
}
}
/* Keep looping till the whole file is sent */
} while (chunksize != 0);
/* Close file after sending complete */
fclose(fd);
ESP_LOGI(TAG, "File sending complete");
/* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
/*上传文件到服务器 */
static esp_err_t upload_post_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
FILE *fd = NULL;
struct stat file_stat;
/* Skip leading "/upload" from URI to get filename */
/* Note sizeof() counts NULL termination hence the -1 */
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
req->uri + sizeof("/upload") - 1, sizeof(filepath));
if (!filename) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
return ESP_FAIL;
}
/* Filename cannot have a trailing '/' */
if (filename[strlen(filename) - 1] == '/') {
ESP_LOGE(TAG, "Invalid filename : %s", filename);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
return ESP_FAIL;
}
if (stat(filepath, &file_stat) == 0) {
ESP_LOGE(TAG, "File already exists : %s", filepath);
//删除文件,并重新上传
unlink(filepath);
/* Respond with 400 Bad Request */
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "文件已经存在,将会被替换");
// return ESP_FAIL;
}
/* File cannot be larger than a limit */
if (req->content_len > MAX_FILE_SIZE) {
ESP_LOGE(TAG, "File too large : %d bytes", req->content_len);
/* Respond with 400 Bad Request */
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
"File size must be less than "
MAX_FILE_SIZE_STR "!");
/* Return failure to close underlying connection else the
* incoming file content will keep the socket busy */
return ESP_FAIL;
}
fd = fopen(filepath, "w");
if (!fd) {
ESP_LOGE(TAG, "Failed to create file : %s", filepath);
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Receiving file : %s...", filename);
/* Retrieve the pointer to scratch buffer for temporary storage */
char *buf = ((struct file_server_data *)req->user_ctx)->scratch;
int received;
/* Content length of the request gives
* the size of the file being uploaded */
int remaining = req->content_len;
while (remaining > 0) {
ESP_LOGI(TAG, "Remaining size : %d", remaining);
/* Receive the file part by part into a buffer */
if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) {
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
/* Retry if timeout occurred */
continue;
}
/* In case of unrecoverable error,
* close and delete the unfinished file*/
fclose(fd);
unlink(filepath);
ESP_LOGE(TAG, "File reception failed!");
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
return ESP_FAIL;
}
/* Write buffer content to file on storage */
if (received && (received != fwrite(buf, 1, received, fd))) {
/* Couldn't write everything to file!
* Storage may be full? */
fclose(fd);
unlink(filepath);
ESP_LOGE(TAG, "File write failed!");
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
return ESP_FAIL;
}
/* Keep track of remaining size of
* the file left to be uploaded */
remaining -= received;
}
/* Close file upon upload completion */
fclose(fd);
ESP_LOGI(TAG, "File reception complete");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "文件上传成功");
/* Redirect onto root to see the updated file list */
// httpd_resp_set_status(req, "303 See Other");
// httpd_resp_set_hdr(req, "Location", "/download/");
// httpd_resp_sendstr(req, "File uploaded successfully");
return ESP_OK;
}
/* 服务器删除文件 */
static esp_err_t delete_post_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
struct stat file_stat;
/* Skip leading "/delete" from URI to get filename */
/* Note sizeof() counts NULL termination hence the -1 */
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
req->uri + sizeof("/delete") - 1, sizeof(filepath));
if (!filename) {
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
return ESP_FAIL;
}
/* Filename cannot have a trailing '/' */
if (filename[strlen(filename) - 1] == '/') {
ESP_LOGE(TAG, "Invalid filename : %s", filename);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
return ESP_FAIL;
}
if (stat(filepath, &file_stat) == -1) {
ESP_LOGE(TAG, "File does not exist : %s", filename);
/* Respond with 400 Bad Request */
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File does not exist");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Deleting file : %s", filename);
/* 删除文件 */
unlink(filepath);
/* Redirect onto root to see the updated file list */
httpd_resp_set_status(req, "303 See Other");
httpd_resp_set_hdr(req, "Location", "/download/");
httpd_resp_sendstr(req, "File deleted successfully");
return ESP_OK;
}
static esp_err_t start_webserver(void)
{
static struct file_server_data *server_data = NULL;
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
if (server_data) {
ESP_LOGE(TAG, "File server already started");
return ESP_ERR_INVALID_STATE;
}
/* 为服务器数据分配内存 */
server_data = calloc(1, sizeof(struct file_server_data));
if (!server_data) {
ESP_LOGE(TAG, "Failed to allocate memory for server data");
return ESP_ERR_NO_MEM;
}
strlcpy(server_data->base_path, "/spiffs",sizeof(server_data->base_path));
/* 使用URI通配符匹配函数允许同一处理程序响应多个与通配符方案匹配的不同目标URI */
config.uri_match_fn = httpd_uri_match_wildcard;
ESP_LOGI(TAG, "Starting HTTP Server");
if (httpd_start(&server, &config) != ESP_OK) {
ESP_LOGE(TAG, "Failed to start server!");
return ESP_FAIL;
}
httpd_uri_t wifi = {
.uri = "/wifi",
.method = HTTP_POST,
.handler = wifi_post_handler,
.user_ctx = NULL
};
httpd_uri_t mqtt = {
.uri = "/mqtt",
.method = HTTP_POST,
.handler = mqtt_post_handler,
.user_ctx = NULL
};
httpd_uri_t home = {
.uri = "/",
.method = HTTP_GET,
.handler = home_handler,
.user_ctx = NULL
};
httpd_uri_t file_download = {
.uri = "/download/*",
.method = HTTP_GET,
.handler = download_get_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_uri_t file_upload = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handler,
.user_ctx = server_data
};
httpd_uri_t file_delete = {
.uri = "/delete/*",
.method = HTTP_POST,
.handler = delete_post_handler,
.user_ctx = server_data
};
// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &home);
httpd_register_uri_handler(server, &wifi);
httpd_register_uri_handler(server, &mqtt);
httpd_register_uri_handler(server, &file_download);
httpd_register_uri_handler(server, &file_upload);
httpd_register_uri_handler(server, &file_delete);
return ESP_OK;
}
static void stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
httpd_stop(server);
}
// 初始化spiffs
static esp_err_t init_spiffs(void)
{
ESP_LOGI(TAG, "Initializing SPIFFS");
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
.partition_label = NULL,
.max_files = 5, // This decides the maximum number of files that can be created on the storage
.format_if_mount_failed = true
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return ESP_FAIL;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info(NULL, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
return ESP_FAIL;
}
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
return ESP_OK;
}
void http_server_start(void)
{
ESP_ERROR_CHECK(init_spiffs());
/* Start the server for the first time */
ESP_ERROR_CHECK(start_webserver());
}

View File

@@ -0,0 +1,127 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "https_ota.h"
static const char *TAG = "advanced_https_ota";
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
#define OTA_URL_SIZE 256
static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
{
if (new_app_info == NULL) {
return ESP_ERR_INVALID_ARG;
}
const esp_partition_t *running = esp_ota_get_running_partition();
esp_app_desc_t running_app_info;
if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
}
// #ifndef CONFIG_EXAMPLE_SKIP_VERSION_CHECK
// if (memcmp(new_app_info->version, running_app_info.version, sizeof(new_app_info->version)) == 0) {
// ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
// return ESP_FAIL;
// }
// #endif
return ESP_OK;
}
void advanced_ota_task(void *pvParameter)
{
ESP_LOGI(TAG, "Starting Advanced OTA");
esp_err_t ota_finish_err = ESP_OK;
esp_http_client_config_t config = {
.url = CONFIG_FIRMWARE_UPG_URL,
.cert_pem = (char *)server_cert_pem_start,
.timeout_ms = CONFIG_OTA_RECV_TIMEOUT,
};
#ifdef CONFIG_SKIP_COMMON_NAME_CHECK
config.skip_cert_common_name_check = true;
#endif
esp_https_ota_config_t ota_config = {
.http_config = &config,
};
esp_https_ota_handle_t https_ota_handle = NULL;
esp_err_t err = esp_https_ota_begin(&ota_config, &https_ota_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "ESP HTTPS OTA Begin failed");
vTaskDelete(NULL);
}
esp_app_desc_t app_desc;
err = esp_https_ota_get_img_desc(https_ota_handle, &app_desc);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_https_ota_read_img_desc failed");
goto ota_end;
}
err = validate_image_header(&app_desc);
if (err != ESP_OK) {
ESP_LOGE(TAG, "image header verification failed");
goto ota_end;
}
while (1) {
err = esp_https_ota_perform(https_ota_handle);
if (err != ESP_ERR_HTTPS_OTA_IN_PROGRESS) {
break;
}
//监控OTA升级的进度提供目前为止镜像数据的大小
ESP_LOGD(TAG, "Image bytes read: %d", esp_https_ota_get_image_len_read(https_ota_handle));
}
if (esp_https_ota_is_complete_data_received(https_ota_handle) != true) {
//OTA镜像没有接收完成
ESP_LOGE(TAG, "Complete data was not received.");
}
ota_end:
ota_finish_err = esp_https_ota_finish(https_ota_handle);
if ((err == ESP_OK) && (ota_finish_err == ESP_OK)) {
ESP_LOGI(TAG, "ESP_HTTPS_OTA upgrade successful. Rebooting ...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
esp_restart();
} else {
if (ota_finish_err == ESP_ERR_OTA_VALIDATE_FAILED) {
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
}
ESP_LOGE(TAG, "ESP_HTTPS_OTA upgrade failed %d", ota_finish_err);
vTaskDelete(NULL);
}
}
void app_main(void)
{
// 初始化nvs
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// OTA app分区表比非OTA分区表具有更小的NVS分区大小。这种大小不匹配可能会导致NVS初始化失败。
//如果发生这种情况我们擦除NVS分区并再次初始化NVS
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_wifi_set_ps(WIFI_PS_NONE);
xTaskCreate(&advanced_ota_task, "advanced_ota_task", 1024 * 8, NULL, 5, NULL);
}

View File

@@ -0,0 +1,81 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "i2c_temp.h"
#include "common.h"
#include <stdio.h>
#include "unity.h"
#include "driver/i2c.h"
#include "i2c_bus.h"
#include "esp_system.h"
#include "sht3x.h"
#define I2C_MASTER_SCL_IO (gpio_num_t)IO_SENSOR_SCL /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO (gpio_num_t)IO_SENSOR_SDA /*!< gpio number for I2C master data */
#define I2C_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
static i2c_bus_handle_t i2c_bus = NULL;
static sht3x_handle_t sht3x = NULL;
/**
* @brief i2c master initialization
*/
static void sht3x_init()
{
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = I2C_MASTER_SCL_IO,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_bus = i2c_bus_create(I2C_MASTER_NUM, &conf);
sht3x = sht3x_create(i2c_bus, SHT3x_ADDR_PIN_SELECT_VSS);
sht3x_set_measure_mode(sht3x, SHT3x_PER_2_MEDIUM); /*!< here read data in periodic mode*/
}
void sht3x_deinit()
{
sht3x_delete(&sht3x);
i2c_bus_delete(&i2c_bus);
}
static void sht3x_get_data()
{
float Tem_val, Hum_val;
int cnt = 1000;
while (cnt--) {
if (sht3x_get_humiture(sht3x, &Tem_val, &Hum_val) == 0) {
printf("temperature %.2f°C ", Tem_val);
printf("humidity:%.2f %%\n", Hum_val);
}
vTaskDelay(3000 / portTICK_RATE_MS);
}
}
void i2c_temp_start(void)
{
sht3x_init();
// vTaskDelay(1000 / portTICK_RATE_MS);
// sht3x_get_data();
// sht3x_deinit();
}
//获取空气温湿度
void get_temp_humi(){
if (sht3x_get_humiture(sht3x, &air_temperature, &air_humidity) == 0) {
printf("temperature %.2f°C ", air_temperature);
printf("humidity:%.2f %%\n", air_humidity);
}
}

View File

@@ -0,0 +1,38 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _BUTTON_H_
#define _BUTTON_H_
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "freertos/queue.h"
#include "freertos/timers.h"
#include <freertos/semphr.h>
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "unity.h"
#include "iot_button.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_err.h"
bool is_open;
void button_start(void);
void rf_receiver_start(void);
void radar_start(void);
#endif

View File

@@ -0,0 +1,134 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "freertos/queue.h"
#include "freertos/timers.h"
#include <freertos/semphr.h>
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "unity.h"
#include "iot_button.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_err.h"
#include "driver/gpio.h"
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_spiffs.h"
#define IO_SENSOR_SCL 1 // IIC-SCL
#define IO_SENSOR_SDA 2 // IIC-SDA
#define IO_RADAR_OUT 3 // 雷达模块输入
#define IO_RADAR_CDS 4 // 雷达模块CDS
#define IO_RELAY 5 // 继电器
// 电源灯:红色(接通电源)、 绿色已经联网、蓝色闪烁智能配网长按配网按钮2s进入、黄色闪烁遥控学习长按配置按钮5s进入
// 接收消息和发送消息时、mqtt连接成功 蓝色灯闪烁一次
#define IO_LED_R 11
#define IO_LED_G 12
#define IO_LED_B 13
#define IO_SWITCH_BUTTON 15 // 短按开关、连续短按断网/联网、长按3s重启
#define IO_RF_RECEIVER_D 19 // 433M射频遥控接收
#define IO_RF_RECEIVER_C 20
#define IO_RF_RECEIVER_B 21
#define IO_RF_RECEIVER_A 26
#define IO_RF_LEARN_KEY 33 // RF遥控学习
#define OTA_DIAGNOSTIC 35 // ota升级回滚确认引脚
// #define BROKEN_URL "mqtt://wumei.live:1883"
#define BROKEN_URL "mqtt://wumei.live:1884"
#define BROKEN_SSL_URL "mqtts://test.mosquitto.org:8884"
#define BROKEN_ADMIN "admin"
#define BROKEN_PWD "admin"
#define VERSION "1.0"
#define CATEGORY 1 //1-wifi通断器,2-智能灯,3-智能门锁,4-智能水阀
char ssid[33]; // wifi的SSID
char pwd[65]; // wifi的密码
char owner_id[64]; // 用户ID
char open_broken_url[128]; // 二次开发mqtt服务器地址
char open_account[64]; // 二次开发mqtt账号
char open_pwd[64]; // 二次开发mqtt密码
uint8_t relay_status; // 继电器状态 0-关闭1-打开
uint8_t light_status; // 灯的状态 0-关闭 1-打开
uint8_t light_mode; // 颜色模式 0-固定颜色 1-七彩渐变 2-七彩动感 3-单色渐变 4-白光 5-暖光
uint8_t is_radar; // 是否进入雷达感应
uint8_t is_alarm; // 是否打开报警
uint8_t is_wifi_offline; // 是否离线模式
uint8_t is_open_certifi; // 二次开发是否使用证书
uint8_t is_host; // 是否托管
uint8_t is_rf_control; // 是否使用RF遥控
uint8_t rf_one_func; // 第一个遥控按键功能1-继电器通断2-开关灯开关雷达4-报警开关5-智能配网
uint8_t rf_two_func; // 第二个遥控按键功能
uint8_t rf_three_func; // 第三个遥控按键功能
uint8_t rf_four_func; // 第四个遥控按键功能
uint32_t red; // 红色值
uint32_t green; // 绿色值
uint32_t blue; // 蓝色值
uint32_t brightness; // 亮度0-100
uint32_t light_interval; // 颜色闪烁间隔
uint32_t radar_interval; // 雷达开灯持续时间,单位秒
uint32_t fade_time; // 灯渐变时间
// 全局变量-不需要存储
char device_num[13]; // 设备编号mac地址
int8_t rssi; // wifi信号强度(信号极好4格[-55—— 0]信号好3格[-70—— -55]信号一般2格[-85—— -70]信号差1格[-100—— -85])
uint8_t wifi_status; // wifi连接状态0-未联网1-已联网
uint8_t trigger_source; // 触发源0-无、1-按键、2.手机、3-浏览器、4-射频遥控、5-雷达、6-报警、7-定时
uint8_t is_reset; // 是否重启
uint8_t is_ap; // 是否打开AP
uint8_t is_rf_learn; // 遥控配对
uint8_t is_rf_clear; // 遥控清码
uint8_t is_smart_config; // 智能配网
float device_temp; // 设备温度
float air_temperature; // 空气温度
float air_humidity; // 空气湿度
// 设备重启
void device_restart(void);
// 获取设备编号
void get_device_num(void);
//设备温度初始化
void device_temp_init(void);
// 读取证书
void read_cert(void);
// 打开继电器
void open_relay(void);
//关闭继电器
void close_relay(void);
// 获取rssi
void get_ap_info(void);
// 433接收模块清码
void rf_clear_code(void);
// 433接收模块对码
void rf_learn(void);
#endif

View File

@@ -0,0 +1,26 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _DEVICE_TEMP_H_
#define _DEVICE_TEMP_H_
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/temp_sensor.h"
//获取设备温度
void get_device_temp(void);
#endif

View File

@@ -0,0 +1,31 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _FLASH_ENCRYPT_H_
#define _FLASH_ENCRYPT_H_
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/efuse_reg.h"
#include "esp_efuse.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_partition.h"
#include "esp_flash_encrypt.h"
#include "esp_efuse_table.h"
#define TARGET_CRYPT_CNT_EFUSE ESP_EFUSE_SPI_BOOT_CRYPT_CNT
#define TARGET_CRYPT_CNT_WIDTH 3
void flash_encrypy_start(void);
#endif

View File

@@ -0,0 +1,29 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _HTTP_SERVER_H_
#define _HTTP_SERVER_H_
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include <esp_http_server.h>
void http_server_start(void);
#endif

View File

@@ -0,0 +1,30 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _HTTPS_OTA_H_
#define _HTTPS_OTA_H_
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_http_client.h"
#include "esp_https_ota.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
#endif

View File

@@ -0,0 +1,43 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _I2C_TEMP_H_
#define _I2C_TEMP_H_
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
//##被称为连接符concatenator用来将两个Token连接为一个Token。
#define _I2C_NUMBER(num) I2C_NUM_##num
#define I2C_NUMBER(num) _I2C_NUMBER(num)
// #define I2C_MASTER_NUM I2C_NUMBER(0) // I2C主机端口号
#define I2C_MASTER_FREQ_HZ 100000 // I2C主机时钟频率
#define I2C_MASTER_TX_BUF_DISABLE 0 //I2C主机不需要缓冲区
#define I2C_MASTER_RX_BUF_DISABLE 0 //I2C主机不需要缓冲区
#define WRITE_BIT I2C_MASTER_WRITE // I2C主机写
#define READ_BIT I2C_MASTER_READ // I2C主机读
#define ACK_CHECK_EN 0x1 // I2C主机将检查从机的ack
#define ACK_CHECK_DIS 0x0 // I2C主机将不检查从机的ack
#define ACK_VAL 0x0 // I2C ack值
#define NACK_VAL 0x1 // I2C nack值
//SHT30
#define SHT30_WRITE_ADDR 0x44 //地址
#define CMD_FETCH_DATA_H 0x22 //循环采样参考sht30 datasheet
#define CMD_FETCH_DATA_L 0x36
void i2c_temp_start(void);
//获取空气温湿度
void get_temp_humi();
#endif

View File

@@ -0,0 +1,88 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _LED_H_
#define _LED_H_
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "common.h"
#define LEDC_LS_TIMER LEDC_TIMER_1
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
#define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
#define LEDC_LS_CH1_CHANNEL LEDC_CHANNEL_1
#define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2
// 颜色枚举
typedef enum {
RED = 0,
YELLOW,
GREEN,
CYAN,
BLUE,
PURPLE,
WHITE,
} led_color;
// led灯闪烁的参数
struct led_blink_parameter
{
uint32_t red;
uint32_t green;
uint32_t blue;
uint32_t brightness;
uint8_t times; //0-无限
uint32_t fade_time; //渐变时间
uint8_t mode; //0-固定颜色 1-七彩渐变 2-七彩动感 3-单色渐变 4-白光 5-暖光
uint32_t interval; //渐变、动感模式闪烁间隔 毫秒
} blink_parameter;
void led_start(void);
/**
* @brief 设置灯闪烁
*
* @param red 红色0-255
* @param green 绿色0-255
* @param blue 蓝色0-255
* @param brightness 亮度0-100
* @param fade_tiime 渐变时间 毫秒
* @param times 闪烁次数0-无限次
* @param mode 模式 0-固定颜色 1-七彩渐变 2-七彩动感 3-单色渐变 4-白光 5-暖光
* @param interval 渐变、动感模式闪烁间隔 毫秒
*/
void led_rgb_blink(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_tiime,uint8_t times,uint8_t mode,uint32_t interval);
/**
* @brief 设置灯颜色
*
* @param red 红色
* @param green 绿色
* @param blue 蓝色
* @param brightness 亮度
* @param fade_time 渐变时间
*/
void led_rgb(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_time);
/**
* @brief 设置led灯实时状态
*
*/
void led_status();
#endif

View File

@@ -0,0 +1,31 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _LWIP_SNTP_H_
#define _LWIP_SNTP_H_
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "nvs_flash.h"
#include "esp_sntp.h"
void sntp_start(void);
#endif

View File

@@ -0,0 +1,45 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _MQTT_H_
#define _MQTT_H_
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "common.h"
void mqtt_start(void);
void mqtt_stop(void);
void mqtt_continue(void);
// 发布设备状态
void publishStatus(void);
//发布设备配置
void publishSetting(void);
#endif

View File

@@ -0,0 +1,36 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _MQTT_SSL_H_
#define _MQTT_SSL_H_
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "common.h"
#endif

View File

@@ -0,0 +1,38 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _NATIVE_OTA_H_
#define _NATIVE_OTA_H_
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_http_client.h"
#include "esp_flash_partitions.h"
#include "esp_partition.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "errno.h"
#include "esp_wifi.h"
#define BUFFSIZE 1024
#define HASH_LEN 32 /* SHA-256 digest length */
#define OTA_URL_SIZE 256
void native_ota_start(void);
#endif

View File

@@ -0,0 +1,129 @@
/****************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
****************************************************************************/
#ifndef _NVS_H_
#define _NVS_H_
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
void read_config_data(); //读取nvs存储的配置信息
void write_config_data(); //写入nvs存储的配置信息
//----------------------------char----------------------------//
//写入wifi的SSID
void write_ssid(void);
//读取wifi的SSID
void read_ssid(void);
//写入wifi密码
void write_pwd(void);
//读取wifi密码
void read_pwd(void);
// 写入用户ID
void write_owner_id(void);
// 读取用户ID
void read_owner_id(void);
// 写入二次开发mqtt地址
void write_open_broken_url(void);
// 读取二次开发mqtt地址
void read_open_broken_url(void);
// 写入二次开发mqtt账号
void write_open_account(void);
// 读取二次开发mqtt账号
void read_open_account(void);
// 写入二次开发mqtt密码
void write_open_pwd(void);
// 读取二次开发mqtt密码
void read_open_pwd(void);
//------------------------uint8-----------------------//
void write_relay_status(void);
void read_relay_status(void);
void write_light_status(void);
void read_light_status(void);
void write_red(void);
void read_red(void);
void write_green(void);
void read_green(void);
void write_blue(void);
void read_blue(void);
void write_light_mode(void);
void read_light_mode(void);
void write_brightness(void);
void read_brightness(void);
void write_is_smart_config(void);
void read_is_smart_config(void);
void write_is_ap(void);
void read_is_ap(void);
void write_is_radar(void);
void read_is_radar(void);
void write_is_alarm(void);
void read_is_alarm(void);
void write_is_wifi_offline(void);
void read_is_wifi_offline(void);
void write_is_open_certifi(void);
void read_is_open_certifi(void);
void write_is_host(void);
void read_is_host(void);
void write_is_rf_control(void);
void read_is_rf_control(void);
void write_rf_one_func(void);
void read_rf_one_func(void);
void write_rf_two_func(void);
void read_rf_two_func(void);
void write_rf_three_func(void);
void read_rf_three_func(void);
void write_rf_four_func(void);
void read_rf_four_func(void);
//----------------------------uint32-----------------------------//
void write_light_interval(void);
void read_light_interval(void);
void write_radar_interval(void);
void read_radar_interval(void);
void write_fade_time(void);
void read_fade_time(void);
#endif

View File

@@ -0,0 +1,32 @@
/**************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
*************************************************************************/
#ifndef _SMART_CONFIG_H_
#define _SMART_CONFIG_H_
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
void smart_config_start(void);
#endif

View File

@@ -0,0 +1,32 @@
/************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
************************************************************************/
#ifndef _STATISTIC_FREE_RTOS_H_
#define _STATISTIC_FREE_RTOS_H_
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#define NUM_OF_SPIN_TASKS 6
#define SPIN_ITER 500000 //实际使用的CPU周期取决于编译器优化
#define SPIN_TASK_PRIO 2
#define STATS_TASK_PRIO 3
#define STATS_TICKS pdMS_TO_TICKS(1000)
#define ARRAY_SIZE_OFFSET 5 //如果print_real_time返回ESP_ERR_INVALID_SIZE则增加此值
void free_rtos_start(void);
#endif

View File

@@ -0,0 +1,26 @@
/*****************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#ifndef _STATISTIC_PERFMON_H_
#define _STATISTIC_PERFMON_H_
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "esp_timer.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "sdkconfig.h"
#include "perfmon.h"
void perfmon_start(void);
#endif

View File

@@ -0,0 +1,46 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
*****************************************************************************/
#ifndef _WIFI_H_
#define _WIFI_H_
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#define LISTEN_INTERVAL 3 //站监听AP信标的间隔。监听间隔的单位是一个信标间隔。例如如果信标间隔为100 ms侦听间隔为3则站侦听信标的间隔为300 ms。
#define POWER_SAVE_MODE WIFI_PS_MIN_MODEM
#define MAXIMUM_RETRY 5
#define AP_SSID "wumei"
#define AP_PASS "wumei.live"
#define AP_CHANNEL 1 //wifi频道1-13的值
#define AP_MAX_STA_CONN 4
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
void wifi_start(void);
void wifi_mqtt_stop(void);
void wifi_continue(void);
void ap_start(void);
#endif

View File

@@ -0,0 +1,292 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "led.h"
#include "wifi.h"
#include "nvs_storage.h"
static TaskHandle_t led_blink_handle = NULL;
static ledc_channel_config_t ledc_channel[3];
static eTaskState state=eDeleted;
static const char* TAG = "led";
//灯颜色设置颜色0-255亮度0-100,fade_time>0则渐变
static void led_rgb_set(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_time){
uint32_t red_duty=0;
uint32_t green_duty=0;
uint32_t blue_duty=0;
// 13位分辨率值为0-8191倍数为32.121
if(CATEGORY==2){
red_duty=(uint32_t)(red*32.121*brightness/100);
green_duty=(uint32_t)(green*32.121*brightness/100);
blue_duty=(uint32_t)(blue*32.121*brightness/100);
}else{
red_duty=8191-(red*32.121*brightness/100);
green_duty=8191-(green*32.121*brightness/100);
blue_duty=8191-(blue*32.121*brightness/100);
}
if(red_duty>8191) {red_duty=8191;}
if(red_duty<0) {red_duty=0;}
if(green_duty>8191) {green_duty=8191;}
if(green_duty<0) {green_duty=0;}
if(blue_duty>8191) {blue_duty=8191;}
if(blue_duty<0) {blue_duty=0;}
ledc_set_fade_with_time(ledc_channel[0].speed_mode, ledc_channel[0].channel, red_duty, fade_time);
ledc_fade_start(ledc_channel[0].speed_mode, ledc_channel[0].channel, LEDC_FADE_NO_WAIT);
ledc_set_fade_with_time(ledc_channel[1].speed_mode, ledc_channel[1].channel, green_duty, fade_time);
ledc_fade_start(ledc_channel[1].speed_mode, ledc_channel[1].channel, LEDC_FADE_NO_WAIT);
ledc_set_fade_with_time(ledc_channel[2].speed_mode, ledc_channel[2].channel, blue_duty, fade_time);
ledc_fade_start(ledc_channel[2].speed_mode, ledc_channel[2].channel, LEDC_FADE_NO_WAIT);
}
//灯闪烁任务
static void led_blink_task(void *arg)
{
ESP_LOGI(TAG, "led blink");
uint32_t i=0;
while(i<blink_parameter.times || blink_parameter.times==0){
switch (blink_parameter.mode)
{
//单色渐变
case 3:
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(blink_parameter.red,blink_parameter.green,blink_parameter.blue,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
break;
// 七彩渐变
case 1:
led_rgb_set(255,0,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,255,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,255,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,255,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,255,255,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,0,255,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,128,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(128,255,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,0,128,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,85,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(128,128,255,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(255,170,0,blink_parameter.brightness,blink_parameter.fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
break;
// 七彩动感
case 2:
//红色
led_rgb_set(255,0,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//绿色
led_rgb_set(0,255,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//蓝色
led_rgb_set(0,0,255,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//黄色
led_rgb_set(255,255,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.fade_time));
//青色
led_rgb_set(0,255,255,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//紫色
led_rgb_set(255,0,255,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//橙色
led_rgb_set(255,128,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//黄绿色
led_rgb_set(128,255,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//玫红
led_rgb_set(255,0,128,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//朱红
led_rgb_set(255,85,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//靛色
led_rgb_set(128,128,255,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
//琥珀色
led_rgb_set(255,170,0,blink_parameter.brightness,fade_time);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
led_rgb_set(0,0,0,0,0);
vTaskDelay(pdMS_TO_TICKS(blink_parameter.interval));
break;
default:
break;
}
vTaskDelay(pdMS_TO_TICKS(100));
i++;
}
if(wifi_status==1)
{
led_rgb_set(0,255,0,2,0);
}else{
led_rgb_set(255,0,0,2,0);
}
vTaskDelete(led_blink_handle);
}
//灯闪烁配置
static void led_blink_config(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_time,uint8_t times,uint8_t mode,uint32_t interval){
blink_parameter.red=red;
blink_parameter.green=green;
blink_parameter.blue=blue;
blink_parameter.brightness=brightness;
blink_parameter.fade_time=fade_time;
blink_parameter.times=times;
blink_parameter.mode=mode;
blink_parameter.interval=interval;
}
// 设置灯颜色
void led_rgb(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_time){
// 删除闪烁任务
if(led_blink_handle!=NULL){
state=eTaskGetState(led_blink_handle);
if(state==eBlocked )
{
vTaskDelete(led_blink_handle);
}
}
led_rgb_set(red,green,blue,brightness,fade_time);
}
//灯闪烁
void led_rgb_blink(uint32_t red,uint32_t green,uint32_t blue, uint32_t brightness,uint32_t fade_time,uint8_t times,uint8_t mode,uint32_t interval)
{
led_blink_config(red,green,blue,brightness,fade_time,times,mode,interval);
// 删除灯闪烁任务
if(led_blink_handle!=NULL){
state=eTaskGetState(led_blink_handle);
if(state==eBlocked )
{
vTaskDelete(led_blink_handle);
}
}
xTaskCreate(led_blink_task,"led_blink_task",2048,NULL,10,&led_blink_handle);
}
//根据状态显示颜色(0-未连接1-已连接)
void led_status(){
if(CATEGORY!=2){
// wifi通断器
if(wifi_status==1)
{
led_rgb(0,255,0,2,0);
}else{
led_rgb(255,0,0,2,0);
}
}else{
// 智能灯
if(light_status==1){
if(light_mode==1 || light_mode==2 || light_mode==3)
{
led_rgb_blink(red,green,blue,brightness,fade_time,0,light_mode,light_interval);
}else{
led_rgb(red,green,blue,brightness,fade_time);
ESP_LOGI(TAG,"red:%d,green:%d,blue:%d,brightness:%d,fade_time:%d",red,green,blue,brightness,fade_time);
}
}else{
// 关灯
led_rgb(0,0,0,0,0);
}
}
}
//led灯启动
void led_start(void)
{
//初始化电源灯和状态灯
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, // PWM占空比分辨率
.freq_hz = 5000, // PWM信号频率
.speed_mode = LEDC_LOW_SPEED_MODE, // 计时器模式
.timer_num = LEDC_TIMER_1, // 计时器索引
.clk_cfg = LEDC_AUTO_CLK, // 自动选择时钟源
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t channel_0={
.channel = LEDC_CHANNEL_0,
.duty = 0,
.gpio_num = IO_LED_R,
.speed_mode = LEDC_LOW_SPEED_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER_1
};
ledc_channel_config_t channel_1={
.channel = LEDC_CHANNEL_1,
.duty = 0,
.gpio_num = IO_LED_G,
.speed_mode = LEDC_LOW_SPEED_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER_1
};
ledc_channel_config_t channel_2={
.channel = LEDC_CHANNEL_2,
.duty = 0,
.gpio_num = IO_LED_B,
.speed_mode = LEDC_LOW_SPEED_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER_1
};
ledc_channel[0]=channel_0; //电源灯-红色
ledc_channel[1]=channel_1; //电源灯-绿色
ledc_channel[2]=channel_2; //电源灯-蓝色
ledc_channel_config(&ledc_channel[0]);
ledc_channel_config(&ledc_channel[1]);
ledc_channel_config(&ledc_channel[2]);
ledc_fade_func_install(0);
led_status();
}

View File

@@ -0,0 +1,78 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "lwip_sntp.h"
static const char *TAG = "sntp";
static void obtain_time(void);
void sntp_start(void)
{
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
ESP_LOGI(TAG, "Connecting to WiFi and getting time over NTP.");
obtain_time();
// 使用当前时间更新'now'变量
time(&now);
char strftime_buf[64];
// 将时区设置为东部标准时间并打印本地时间
setenv("TZ", "EST5EDT,M3.2.0/2,M11.1.0", 1);
tzset();
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
ESP_LOGI(TAG, "The current date/time in New York is: %s", strftime_buf);
// 设置时区为中国标准时间
setenv("TZ", "CST-8", 1);
tzset();
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
ESP_LOGI(TAG, "The current date/time in Shanghai is: %s", strftime_buf);
}
//时间同步通知的回调函数
void time_sync_notification_cb(struct timeval *tv)
{
ESP_LOGI(TAG, "Notification of a time synchronization event");
}
//获取时间
static void obtain_time(void)
{
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "ntp1.aliyun.com");
sntp_setservername(1, "time2.cloud.tencent.com");
sntp_setservername(2, "ntp.ntsc.ac.cn");
sntp_setservername(3, "pool.ntp.org");
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
sntp_init();
// 等待时间设定
time_t now = 0;
struct tm timeinfo = { 0 };
int retry = 0;
const int retry_count = 10;
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
time(&now);
localtime_r(&now, &timeinfo);
}

View File

@@ -0,0 +1,102 @@
/******************************************************************************
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include <stdio.h>
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "nvs.h"
#include "esp_pm.h"
#include "button.h"
#include "common.h"
#include "device_temp.h"
#include "i2c_temp.h"
#include "led.h"
#include "mqtt.h"
#include "smart_config.h"
#include "lwip_sntp.h"
#include "wifi.h"
#include "nvs_storage.h"
// #include "mqtt_ssl.h"
// #include "native_ota.h"
// #include "flash_encrypt.h"
// #include "statistic_free_rtos.h"
// #include "statistic_perfmon.h"
static const char *TAG = "wumei-open";
void app_main()
{
esp_log_level_set("*", ESP_LOG_INFO);
ESP_LOGI(TAG, "[wumei-open] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
// 初始化NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
// 默认时间循环
ESP_ERROR_CHECK(esp_event_loop_create_default());
#if CONFIG_PM_ENABLE
// 配置动态频率变化,如果启用了无滴答空闲支持则会启用自动轻度睡眠
esp_pm_config_esp32s2_t pm_config = {
.max_freq_mhz = CONFIG_MAX_CPU_FREQ_MHZ,
.min_freq_mhz = CONFIG_MIN_CPU_FREQ_MHZ,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
.light_sleep_enable = true
#endif
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
#endif
// 读取配置信息
read_config_data();
// 获取设备编号
get_device_num();
// 启动led灯
led_start();
// 启动按钮
button_start();
// 启动射频遥控接收
rf_receiver_start();
// 启动雷达感应
// radar_start();
// wifi
if(is_wifi_offline==0){
//连接wifi
wifi_start();
// 启动mqtt
mqtt_start();
//获取SNTP时间
// sntp_start();
}
// 初始化设备温度
device_temp_init();
// 初始化空气温湿度
// i2c_temp_start();
//设备性能监测
// ESP_LOGI(TAG, "start perfmon");
// perfmon_start();
//FreeRTOS监测
// vTaskDelay(pdMS_TO_TICKS(2000));
// ESP_LOGI(TAG, "start free rtos statistic");
// free_rtos_start();
}

View File

@@ -0,0 +1,432 @@
/******************************************************************************
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "mqtt.h"
#include "led.h"
#include "common.h"
#include "cJSON.h"
#include "cJSON_Utils.h"
#include "nvs_storage.h"
#include "driver/temp_sensor.h"
#include "i2c_temp.h"
#include "wifi.h"
static const char *TAG = "MQTT";
static esp_mqtt_client_handle_t mqtt_client=NULL;
static char *update_status_topic;
static char *get_status_topic;
static char *update_setting_topic;
static char *get_setting_topic;
// 发布设备状态
void publishStatus(void){
// temp_sensor_read_celsius(&device_temp); //获取设备温度
// get_temp_humi(); // 获取空气温湿度
get_ap_info(); //获取wifi信号
cJSON *status = cJSON_CreateObject();
cJSON_AddStringToObject(status,"deviceNum",device_num);
cJSON_AddNumberToObject(status,"relayStatus",relay_status);
cJSON_AddNumberToObject(status,"lightStatus",light_status);
cJSON_AddNumberToObject(status,"isOnline",1);
cJSON_AddNumberToObject(status,"rssi",rssi);
cJSON_AddNumberToObject(status,"deviceTemperature",device_temp);
cJSON_AddNumberToObject(status,"airTemperature",air_temperature);
cJSON_AddNumberToObject(status,"airHumidity",air_humidity);
cJSON_AddNumberToObject(status,"triggerSource",trigger_source);
cJSON_AddNumberToObject(status,"brightness",brightness);
cJSON_AddNumberToObject(status,"lightInterval",light_interval);
cJSON_AddNumberToObject(status,"lightMode",light_mode);
cJSON_AddNumberToObject(status,"fadeTime",fade_time);
cJSON_AddNumberToObject(status,"red",red);
cJSON_AddNumberToObject(status,"green",green);
cJSON_AddNumberToObject(status,"blue",blue);
char *status_msg = cJSON_Print(status);
//释放内存
cJSON_Delete(status);
ESP_LOGI(TAG,"status msg: %s",status_msg);
int msg_id=esp_mqtt_client_publish(mqtt_client,"status",status_msg,0,1,0);
ESP_LOGI(TAG, "sent publish device status, msg_id=%d",msg_id);
}
//发布设备配置
void publishSetting(void){
cJSON *setting = cJSON_CreateObject();
cJSON_AddStringToObject(setting,"deviceNum",device_num);
cJSON_AddNumberToObject(setting,"isAlarm",is_alarm);
cJSON_AddNumberToObject(setting,"isRadar",is_radar);
cJSON_AddNumberToObject(setting,"isHost",is_host);
cJSON_AddNumberToObject(setting,"isRfControl",is_rf_control);
cJSON_AddNumberToObject(setting,"rfOneFunc",rf_one_func);
cJSON_AddNumberToObject(setting,"rfTwoFunc",rf_two_func);
cJSON_AddNumberToObject(setting,"rfThreeFunc",rf_three_func);
cJSON_AddNumberToObject(setting,"rfFourFunc",rf_four_func);
cJSON_AddStringToObject(setting,"ownerId",owner_id);
cJSON_AddNumberToObject(setting,"isReset",is_reset);
cJSON_AddNumberToObject(setting,"isAp",is_ap);
cJSON_AddNumberToObject(setting,"isRfLearn",is_rf_learn);
cJSON_AddNumberToObject(setting,"isRfClear",is_rf_clear);
cJSON_AddNumberToObject(setting,"isSmartConfig",is_smart_config);
cJSON_AddNumberToObject(setting,"radarInterval",radar_interval);
cJSON_AddNumberToObject(setting,"isWifiOffline",is_wifi_offline);
cJSON_AddNumberToObject(setting,"isOpenCertifi",is_open_certifi);
char *setting_msg = cJSON_Print(setting);
//释放内存
cJSON_Delete(setting);
ESP_LOGI(TAG,"setting msg: %s",setting_msg);
int msg_id=esp_mqtt_client_publish(mqtt_client,"setting",setting_msg,0,1,0);
ESP_LOGI(TAG, "sent publish device setting, msg_id=%d",msg_id);
}
// 更新设备状态
static void updateStatus(esp_mqtt_event_handle_t event,char *topic){
//将字符串格式的json数据转化为JSON对象格式
cJSON *root = cJSON_Parse(event->data);
if(root == NULL) { printf("parse error\n"); }
cJSON *value_relay = cJSON_GetObjectItem(root, "relayStatus");
char *relay = cJSON_Print(value_relay);
relay_status=atoi(relay);
//打开关闭继电器
if(relay_status==1){
open_relay();
}else{
close_relay();
}
free(relay);
cJSON *value_trigger = cJSON_GetObjectItem(root, "triggerSource");
char *trigger = cJSON_Print(value_trigger);
trigger_source=atoi(trigger);
free(trigger);
cJSON *value_brightness = cJSON_GetObjectItem(root, "brightness");
char *bright = cJSON_Print(value_brightness);
brightness=atoi(bright);
free(bright);
cJSON *value_interval = cJSON_GetObjectItem(root, "lightInterval");
char *interval = cJSON_Print(value_interval);
light_interval=atoi(interval);
free(interval);
cJSON *value_mode = cJSON_GetObjectItem(root, "lightMode");
char *mode = cJSON_Print(value_mode);
light_mode=atoi(mode);
free(mode);
cJSON *value_fade = cJSON_GetObjectItem(root, "fadeTime");
char *fade = cJSON_Print(value_fade);
fade_time=atoi(fade);
free(fade);
cJSON *value_red = cJSON_GetObjectItem(root, "red");
char *red_string = cJSON_Print(value_red);
red=atoi(red_string);
free(red_string);
cJSON *value_green = cJSON_GetObjectItem(root, "green");
char *green_string = cJSON_Print(value_green);
green=atoi(green_string);
free(green_string);
cJSON *value_blue = cJSON_GetObjectItem(root, "blue");
char *blue_string = cJSON_Print(value_blue);
blue=atoi(blue_string);
free(blue_string);
cJSON *value_light = cJSON_GetObjectItem(root, "lightStatus");
char *light = cJSON_Print(value_light);
light_status=atoi(light);
//打开关闭彩灯
free(light);
//更新灯状态并存储
led_status();
write_config_data();
cJSON_Delete(root);
}
//更新设备配置
static void updateSetting(esp_mqtt_event_handle_t event,char *topic){
//将字符串格式的json数据转化为JSON对象格式
cJSON *root = cJSON_Parse(event->data);
if(root == NULL) { printf("parse error\n"); }
cJSON *value_alarm = cJSON_GetObjectItem(root, "isAlarm");
char *alarm = cJSON_Print(value_alarm);
is_alarm=atoi(alarm);
free(alarm);
cJSON *value_radar = cJSON_GetObjectItem(root, "isRadar");
char *radar = cJSON_Print(value_radar);
is_radar=atoi(radar);
free(radar);
cJSON *value_host = cJSON_GetObjectItem(root, "isHost");
char *host = cJSON_Print(value_host);
is_host=atoi(host);
free(host);
cJSON *value_rf = cJSON_GetObjectItem(root, "isRfControl");
char *rf = cJSON_Print(value_rf);
is_rf_control=atoi(rf);
free(rf);
cJSON *value_rf_one = cJSON_GetObjectItem(root, "rfOneFunc");
char *rf_one = cJSON_Print(value_rf_one);
rf_one_func=atoi(rf_one);
free(rf_one);
cJSON *value_rf_two = cJSON_GetObjectItem(root, "rfTwoFunc");
char *rf_two = cJSON_Print(value_rf_two);
rf_two_func=atoi(rf_two);
free(rf_two);
cJSON *value_rf_three = cJSON_GetObjectItem(root, "rfThreeFunc");
char *rf_three = cJSON_Print(value_rf_three);
rf_three_func=atoi(rf_three);
free(rf_three);
cJSON *value_rf_four = cJSON_GetObjectItem(root, "rfFourFunc");
char *rf_four = cJSON_Print(value_rf_four);
rf_four_func=atoi(rf_four);
free(rf_four);
cJSON *value_rf_learn = cJSON_GetObjectItem(root, "isRfLearn");
char *rf_learning = cJSON_Print(value_rf_learn);
if(strcmp(rf_learning, "1") == 0){
// 遥控配对
rf_learn();
}
free(rf_learning);
cJSON *value_rf_clear = cJSON_GetObjectItem(root, "isRfClear");
char *rf_clear = cJSON_Print(value_rf_clear);
if(strcmp(rf_clear, "1") == 0){
// 遥控清码
rf_clear_code();
}
free(rf_clear);
cJSON *value_ap = cJSON_GetObjectItem(root, "isAp");
char *ap = cJSON_Print(value_ap);
if(strcmp(ap, "1") == 0){
// 打开AP
if(is_ap!=1){
// 打开ap
ESP_LOGI(TAG, "open access point \n");
is_ap=1;
ap_start();
}
}
free(ap);
//写入配置
write_config_data();
cJSON *value_reset = cJSON_GetObjectItem(root, "isReset");
char *reset = cJSON_Print(value_reset);
if(strcmp(reset, "1") == 0){
// 设备重启
device_restart();
}
free(reset);
cJSON_Delete(root);
}
static void mqtt_subscribe_event(esp_mqtt_event_handle_t event)
{
char topic[32];
ESP_LOGI(TAG,"event topic:%.*s\r", event->topic_len, event->topic);
ESP_LOGI(TAG,"event data:%.*s\r\n",event->data_len, event->data);
sprintf(topic,"%.*s", event->topic_len, event->topic);
if (strcmp(topic, update_status_topic) == 0)
{
//更新设备状态
updateStatus(event,topic);
// 发布设备状态
publishStatus();
} else if (strcmp(topic, get_status_topic) == 0)
{
publishStatus();
}else if(strcmp(topic,update_setting_topic) == 0){
// 更新设备配置
updateSetting(event,topic);
// 发布设备配置
publishSetting();
}
else if(strcmp(topic, get_setting_topic) == 0)
{
publishSetting();
}
}
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
int msg_id;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
//-----------------------------------订阅消息----------------------------------------
// 订阅更新设备状态
msg_id = esp_mqtt_client_subscribe(mqtt_client, update_status_topic, 1);
ESP_LOGI(TAG, "sent subscribe set status successful, msg_id=%d,topic=%s", msg_id,update_status_topic);
// 订阅获取设备状态
msg_id = esp_mqtt_client_subscribe(mqtt_client, get_status_topic, 1);
ESP_LOGI(TAG, "sent subscribe get status successful, msg_id=%d,topic=%s", msg_id,get_status_topic);
// 订阅更新设备配置
msg_id = esp_mqtt_client_subscribe(mqtt_client, update_setting_topic, 1);
ESP_LOGI(TAG, "sent subscribe set setting successful, msg_id=%d,topic=%s", msg_id,update_setting_topic);
// 订阅获取设备配置
msg_id = esp_mqtt_client_subscribe(mqtt_client, get_setting_topic, 1);
ESP_LOGI(TAG, "sent subscribe get setting successful, msg_id=%d,topic=%s", msg_id,get_setting_topic);
//-----------------------------------发布消息--------------------------------------
//发布设备信息
cJSON *device_info = cJSON_CreateObject();
cJSON_AddStringToObject(device_info,"deviceNum",device_num);
cJSON_AddNumberToObject(device_info,"categoryId",CATEGORY);
cJSON_AddStringToObject(device_info,"firmwareVersion",VERSION);
cJSON_AddStringToObject(device_info,"ownerId",owner_id);
char *device_msg = cJSON_Print(device_info);
//释放内存
cJSON_Delete(device_info);
ESP_LOGI(TAG,"device msg: %s",device_msg);
msg_id=esp_mqtt_client_publish(mqtt_client,"device_info",device_msg,0,1,0);
ESP_LOGI(TAG, "sent publish device info, msg_id=%d",msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
//订阅事件处理
mqtt_subscribe_event(event);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
return ESP_OK;
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
mqtt_event_handler_cb(event_data);
}
// 配置订阅主题
static void config_topic(){
static char *update_status_path="status/set/";
static char *get_status_path="status/get/";
static char *update_setting_path="setting/set/";
static char *get_setting_path="setting/get/";
// 更新状态
update_status_topic=(char *)malloc(strlen(update_status_path)+strlen(device_num)+1);
if(update_status_topic==NULL){
ESP_LOGD(TAG, "failed to apply for memory");
}
strcpy(update_status_topic,update_status_path);
strcat(update_status_topic,device_num);
ESP_LOGI(TAG,"update_status_topic:%s",update_status_topic);
// 获取状态
get_status_topic=(char *)malloc(strlen(get_status_path)+strlen(device_num)+1);
if(get_status_topic==NULL){
ESP_LOGD(TAG, "failed to apply for memory");
}
strcpy(get_status_topic,get_status_path);
strcat(get_status_topic,device_num);
ESP_LOGI(TAG,"get_status_topic:%s",get_status_topic);
// 更新配置
update_setting_topic=(char *)malloc(strlen(update_setting_path)+strlen(device_num)+1);
if(update_setting_topic==NULL){
ESP_LOGD(TAG, "failed to apply for memory");
}
strcpy(update_setting_topic,update_setting_path);
strcat(update_setting_topic,device_num);
ESP_LOGI(TAG,"update_setting_topic:%s",update_setting_topic);
// 获取配置
get_setting_topic=(char *)malloc(strlen(get_setting_path)+strlen(device_num)+1);
if(get_setting_topic==NULL){
ESP_LOGD(TAG, "failed to apply for memory");
}
strcpy(get_setting_topic,get_setting_path);
strcat(get_setting_topic,device_num);
ESP_LOGI(TAG,"get_setting_topic:%s",get_setting_topic);
}
void mqtt_start(void)
{
// esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
esp_log_level_set("MQTT", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
// 配置订阅的主题
config_topic();
// 遗嘱消息内容
cJSON *root = cJSON_CreateObject();
cJSON_AddStringToObject(root,"deviceNum",device_num);
cJSON_AddNumberToObject(root,"isOnline",0);
char *will_msg = cJSON_Print(root);
//释放内存
cJSON_Delete(root);
ESP_LOGI(TAG,"last will: %s", will_msg);
esp_mqtt_client_config_t mqtt_cfg = {
.uri = BROKEN_URL,
.username = BROKEN_ADMIN,
.password = BROKEN_PWD,
//设置遗嘱
.lwt_topic="offline",
.lwt_msg=will_msg,
.lwt_msg_len=strlen(will_msg),
.lwt_qos=1,
.lwt_retain=0,
//断开前等待的时间,3秒
.keepalive=3,
};
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, mqtt_client);
esp_mqtt_client_start(mqtt_client);
}
void mqtt_stop(void){
if(mqtt_client!=NULL){
esp_mqtt_client_stop(mqtt_client);
}
}
void mqtt_continue(void){
if(mqtt_client!=NULL){
esp_mqtt_client_start(mqtt_client);
}
}

View File

@@ -0,0 +1,98 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "mqtt_ssl.h"
static const char *TAG = "MQTTS";
extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start");
extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end");
extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start");
extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end");
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
return ESP_OK;
}
static void mqtt_app_start(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.uri = BROKEN_SSL_URL,
.event_handle = mqtt_event_handler,
.client_cert_pem = (const char *)client_cert_pem_start,
.client_key_pem = (const char *)client_key_pem_start,
};
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_start(client);
}
void mqtt_ssl_start(void)
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
mqtt_app_start();
}

View File

@@ -0,0 +1,287 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "native_ota.h"
static const char *TAG = "native_ota";
/*准备写入Flash的OTA数据写入缓冲区*/
static char ota_write_data[BUFFSIZE + 1] = { 0 };
// extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
//extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
static void http_cleanup(esp_http_client_handle_t client)
{
esp_http_client_close(client);
esp_http_client_cleanup(client);
}
static void __attribute__((noreturn)) task_fatal_error(void)
{
ESP_LOGE(TAG, "Exiting task due to fatal error...");
(void)vTaskDelete(NULL);
while (1) {
;
}
}
static void print_sha256 (const uint8_t *image_hash, const char *label)
{
char hash_print[HASH_LEN * 2 + 1];
hash_print[HASH_LEN * 2] = 0;
for (int i = 0; i < HASH_LEN; ++i) {
sprintf(&hash_print[i * 2], "%02x", image_hash[i]);
}
ESP_LOGI(TAG, "%s: %s", label, hash_print);
}
static void infinite_loop(void)
{
int i = 0;
ESP_LOGI(TAG, "When a new firmware is available on the server, press the reset button to download it");
while(1) {
ESP_LOGI(TAG, "Waiting for a new firmware ... %d", ++i);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
static void ota_task(void *pvParameter)
{
esp_err_t err;
/* 更新句柄 : 由 esp_ota_begin()设置, 必须通过esp_ota_end()释放 */
esp_ota_handle_t update_handle = 0 ;
const esp_partition_t *update_partition = NULL;
ESP_LOGI(TAG, "Starting OTA...");
const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition();
if (configured != running) {
ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
configured->address, running->address);
ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
}
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
running->type, running->subtype, running->address);
esp_http_client_config_t config = {
.url = CONFIG_FIRMWARE_UPG_URL,
//.cert_pem = (char *)server_cert_pem_start,
.timeout_ms = CONFIG_OTA_RECV_TIMEOUT,
};
#ifdef CONFIG_SKIP_COMMON_NAME_CHECK
config.skip_cert_common_name_check = true;
#endif
esp_http_client_handle_t client = esp_http_client_init(&config);
if (client == NULL) {
ESP_LOGE(TAG, "Failed to initialise HTTP connection");
task_fatal_error();
}
err = esp_http_client_open(client, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
esp_http_client_cleanup(client);
task_fatal_error();
}
esp_http_client_fetch_headers(client);
update_partition = esp_ota_get_next_update_partition(NULL);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
update_partition->subtype, update_partition->address);
assert(update_partition != NULL);
int binary_file_length = 0;
/*处理所有接收到的数据包*/
bool image_header_was_checked = false;
while (1) {
int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE);
if (data_read < 0) {
ESP_LOGE(TAG, "Error: SSL data read error");
http_cleanup(client);
task_fatal_error();
} else if (data_read > 0) {
if (image_header_was_checked == false) {
esp_app_desc_t new_app_info;
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
// 通过下载检查当前版本
memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
esp_app_desc_t running_app_info;
if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
}
const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition();
esp_app_desc_t invalid_app_info;
if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) {
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
}
// 使用最新的无效分区检查当前版本
if (last_invalid_app != NULL) {
if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) {
ESP_LOGW(TAG, "New version is the same as invalid version.");
ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
http_cleanup(client);
infinite_loop();
}
}
#ifndef CONFIG_SKIP_VERSION_CHECK
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
http_cleanup(client);
infinite_loop();
}
#endif
image_header_was_checked = true;
err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
http_cleanup(client);
task_fatal_error();
}
ESP_LOGI(TAG, "esp_ota_begin succeeded");
} else {
ESP_LOGE(TAG, "received package is not fit len");
http_cleanup(client);
task_fatal_error();
}
}
err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read);
if (err != ESP_OK) {
http_cleanup(client);
task_fatal_error();
}
binary_file_length += data_read;
ESP_LOGD(TAG, "Written image length %d", binary_file_length);
} else if (data_read == 0) {
/*
*由于esp_http_client_read永远不会返回负错误代码因此我们依靠`errno`来检查基础传输连接是否关闭
*/
if (errno == ECONNRESET || errno == ENOTCONN) {
ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
break;
}
if (esp_http_client_is_complete_data_received(client) == true) {
ESP_LOGI(TAG, "Connection closed");
break;
}
}
}
ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length);
if (esp_http_client_is_complete_data_received(client) != true) {
ESP_LOGE(TAG, "Error in receiving complete file");
http_cleanup(client);
task_fatal_error();
}
err = esp_ota_end(update_handle);
if (err != ESP_OK) {
if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
}
ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err));
http_cleanup(client);
task_fatal_error();
}
err = esp_ota_set_boot_partition(update_partition);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
http_cleanup(client);
task_fatal_error();
}
ESP_LOGI(TAG, "Prepare to restart system!");
esp_restart();
return ;
}
static bool diagnostic(void)
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_GPIO_DIAGNOSTIC);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
ESP_LOGI(TAG, "Diagnostics (5 sec)...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
bool diagnostic_is_ok = gpio_get_level(CONFIG_GPIO_DIAGNOSTIC);
gpio_reset_pin(CONFIG_GPIO_DIAGNOSTIC);
return diagnostic_is_ok;
}
void native_ota_start(void)
{
uint8_t sha_256[HASH_LEN] = { 0 };
esp_partition_t partition;
// 获取分区表的sha256摘要
partition.address = ESP_PARTITION_TABLE_OFFSET;
partition.size = ESP_PARTITION_TABLE_MAX_LEN;
partition.type = ESP_PARTITION_TYPE_DATA;
esp_partition_get_sha256(&partition, sha_256);
print_sha256(sha_256, "SHA-256 for the partition table: ");
// 获取引导加载程序的sha256摘要
partition.address = ESP_BOOTLOADER_OFFSET;
partition.size = ESP_PARTITION_TABLE_OFFSET;
partition.type = ESP_PARTITION_TYPE_APP;
esp_partition_get_sha256(&partition, sha_256);
print_sha256(sha_256, "SHA-256 for bootloader: ");
// 获取运行分区的sha256摘要
esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256);
print_sha256(sha_256, "SHA-256 for current firmware: ");
const esp_partition_t *running = esp_ota_get_running_partition();
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
// 运行诊断功能
bool diagnostic_is_ok = diagnostic();
if (diagnostic_is_ok) {
ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ...");
esp_ota_mark_app_valid_cancel_rollback();
} else {
ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ...");
esp_ota_mark_app_invalid_rollback_and_reboot();
}
}
}
// 初始化 NVS.
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// OTA app分区表比非OTA分区表具有更小的NVS分区大小。这种大小不匹配可能会导致NVS初始化失败。
//如果发生这种情况我们擦除NVS分区并再次初始化NVS
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
ESP_ERROR_CHECK(esp_netif_init());
/* 确保禁用任何WiFi省电模式这将允许最佳吞吐量从而为整个OTA操作计时*/
esp_wifi_set_ps(WIFI_PS_NONE);
xTaskCreate(&ota_task, "ota_task", 8192, NULL, 5, NULL);
}

View File

@@ -0,0 +1,485 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "nvs_storage.h"
#include "common.h"
#include <string.h>
static const char *TAG = "nvs";
//读取字符数据
static esp_err_t nvs_read_str(const char *key,char *out_value)
{
nvs_handle_t read_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &read_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG,"Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
size_t required_size = 0;
err = nvs_get_str(read_handle, key, NULL, &required_size);
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;
if (required_size == 0) {
ESP_LOGI( TAG,"Nothing saved yet! key=%s",key);
} else {
err = nvs_get_str(read_handle, key, out_value, &required_size);
if(err==ESP_OK)
{
ESP_LOGI( TAG, "Get %s success!",key);
}
else
{
ESP_LOGI( TAG, "get err =0x%x",err);
ESP_LOGI( TAG, "Get %s fail!",key);
}
}
err = nvs_commit(read_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
// 关闭
nvs_close(read_handle);
return ESP_OK;
}
//读取uint8数据
static esp_err_t nvs_read_u8(const char *key,uint8_t *out_value)
{
nvs_handle_t read_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &read_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG, "Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
err = nvs_get_u8(read_handle, key, out_value);
if(err==ESP_OK)
{
ESP_LOGI( TAG, "Get %s success!",key);
}
else
{
ESP_LOGI( TAG, "get err =0x%x",err);
ESP_LOGI( TAG, "Get %s fail!",key);
}
err = nvs_commit(read_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
// 关闭
nvs_close(read_handle);
return ESP_OK;
}
//读取uint32数据
static esp_err_t nvs_read_u32(const char *key,uint32_t *out_value)
{
nvs_handle_t read_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &read_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG, "Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
err = nvs_get_u32(read_handle, key, out_value);
if(err==ESP_OK)
{
ESP_LOGI( TAG, "Get %s success!",key);
}
else
{
ESP_LOGI( TAG, "get err =0x%x",err);
ESP_LOGI( TAG, "Get %s fail!",key);
}
err = nvs_commit(read_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
// 关闭
nvs_close(read_handle);
return ESP_OK;
}
//写入字符数据
static void nvs_write_str(const char *key, const char *value)
{
nvs_handle_t write_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &write_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG, "Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
err=nvs_set_str(write_handle,key,value);
if(err==ESP_OK)
ESP_LOGI( TAG, "set %s success!",key);
else
{
ESP_LOGI( TAG, "set %s fail!",key);
}
err = nvs_commit(write_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
nvs_close(write_handle);
}
//写入uint8数据
static void nvs_write_u8(const char *key, uint8_t value)
{
nvs_handle_t write_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &write_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG, "Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
err=nvs_set_u8(write_handle,key,value);
if(err==ESP_OK)
ESP_LOGI( TAG,"set %s success!",key);
else
{
ESP_LOGI( TAG, "set %s fail!",key);
}
err = nvs_commit(write_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
nvs_close(write_handle);
}
//写入uint32数据
static void nvs_write_u32(const char *key, uint32_t value)
{
nvs_handle_t write_handle;
esp_err_t err;
err = nvs_open("wificonfig", NVS_READWRITE, &write_handle);
if (err != ESP_OK) {
ESP_LOGE( TAG, "Error (%s) opening NVS handle! key=%s", esp_err_to_name(err),key);
}
else
{
err=nvs_set_u32(write_handle,key,value);
if(err==ESP_OK)
ESP_LOGI( TAG, "set %s success!",key);
else
{
ESP_LOGI( TAG, "set %s fail!",key);
}
err = nvs_commit(write_handle);
if(err!= ESP_OK){
ESP_LOGE(TAG,"nvs_commit Failed!");
}else{
ESP_LOGI(TAG," nvs_commit Done");
}
}
nvs_close(write_handle);
}
//--------------------------------------------char----------------------------------------------//
// 读取配置信息
void read_config_data(){
read_ssid();
read_pwd();
read_owner_id();
read_relay_status();
read_light_status();
read_red();
read_green();
read_blue();
read_light_mode();
read_brightness();
read_is_smart_config();
read_is_radar();
read_is_alarm();
read_is_wifi_offline();
read_light_interval();
read_radar_interval();
read_fade_time();
read_open_broken_url();
read_open_account();
read_open_pwd();
read_is_open_certifi();
read_is_host();
read_is_rf_control();
read_rf_one_func();
read_rf_two_func();
read_rf_three_func();
read_rf_four_func();
}
// 写入配置信息
void write_config_data(){
write_ssid();
write_pwd();
write_owner_id();
write_relay_status();
write_light_status();
write_red();
write_green();
write_blue();
write_light_mode();
write_brightness();
write_is_smart_config();
write_is_radar();
write_is_alarm();
write_is_wifi_offline();
write_light_interval();
write_radar_interval();
write_fade_time();
write_open_broken_url();
write_open_account();
write_open_pwd();
write_is_open_certifi();
write_is_host();
write_is_rf_control();
write_rf_one_func();
write_rf_two_func();
write_rf_three_func();
write_rf_four_func();
}
//写入wifi的SSID
void write_ssid(void){
nvs_write_str("ssid", ssid);
}
//读取wifi的SSID
void read_ssid(void)
{
nvs_read_str("ssid",ssid);
}
//写入wifi密码
void write_pwd(void){
nvs_write_str("pwd",pwd);
}
//读取wifi密码
void read_pwd(void){
nvs_read_str("pwd",pwd);
}
//写入用户ID
void write_owner_id(void){
nvs_write_str("owner_id",owner_id);
}
//读取用户ID
void read_owner_id(void){
nvs_read_str("owner_id",owner_id);
}
//写入二次开发mqtt地址
void write_open_broken_url(void){
nvs_write_str("open_broken_url",open_broken_url);
}
//读取二次开发mqtt地址
void read_open_broken_url(void){
nvs_read_str("open_broken_url",open_broken_url);
}
//写入二次开发mqtt账号
void write_open_account(void){
nvs_write_str("open_account",open_account);
}
//读取二次开发mqtt账号
void read_open_account(void){
nvs_read_str("open_account",open_account);
}
//写入二次开发mqtt密码
void write_open_pwd(void){
nvs_write_str("open_pwd",open_pwd);
}
//读取二次开发mqtt密码
void read_open_pwd(void){
nvs_read_str("open_pwd",open_pwd);
}
//--------------------------------------------uint8----------------------------------------------//
void write_relay_status(void){
nvs_write_u8("relay_status",relay_status);
}
void read_relay_status(void){
nvs_read_u8("relay_status",&relay_status);
}
void write_light_status(void){
nvs_write_u8("light_status",light_status);
}
void read_light_status(void){
nvs_read_u8("light_status",&light_status);
}
void write_light_mode(void){
nvs_write_u8("light_mode",light_mode);
}
void read_light_mode(void){
nvs_read_u8("light_mode",&light_mode);
}
void write_is_smart_config(void){
nvs_write_u8("is_smart_config",is_smart_config);
}
void read_is_smart_config(void){
nvs_read_u8("is_smart_config",&is_smart_config);
}
void write_is_radar(void){
nvs_write_u8("is_radar",is_radar);
}
void read_is_radar(void){
nvs_read_u8("is_radar",&is_radar);
}
void write_is_alarm(void){
nvs_write_u8("is_alarm",is_alarm);
}
void read_is_alarm(void){
nvs_read_u8("is_alarm",&is_alarm);
}
void write_is_wifi_offline(void){
nvs_write_u8("is_wifi_offline",is_wifi_offline);
}
void read_is_wifi_offline(void){
nvs_read_u8("is_wifi_offline",&is_wifi_offline);
}
void write_is_open_certifi(void){
nvs_write_u8("is_open_certifi",is_open_certifi);
}
void read_is_open_certifi(void){
nvs_read_u8("is_open_certifi",&is_open_certifi);
}
void write_is_host(void){
nvs_write_u8("is_host",is_host);
}
void read_is_host(void){
nvs_read_u8("is_host",&is_host);
}
void write_is_rf_control(void){
nvs_write_u8("is_rf_control",is_rf_control);
}
void read_is_rf_control(void){
nvs_read_u8("is_rf_control",&is_rf_control);
}
void write_rf_one_func(void){
nvs_write_u8("rf_one_func",rf_one_func);
}
void read_rf_one_func(void){
nvs_read_u8("rf_one_func",&rf_one_func);
}
void write_rf_two_func(void){
nvs_write_u8("rf_two_func",rf_two_func);
}
void read_rf_two_func(void){
nvs_read_u8("rf_two_func",&rf_two_func);
}
void write_rf_three_func(void){
nvs_write_u8("rf_three_func",rf_three_func);
}
void read_rf_three_func(void){
nvs_read_u8("rf_three_func",&rf_three_func);
}
void write_rf_four_func(void){
nvs_write_u8("rf_four_func",rf_four_func);
}
void read_rf_four_func(void){
nvs_read_u8("rf_four_func",&rf_four_func);
}
//--------------------------------------------------uint32----------------------------------------------//
void write_red(void){
nvs_write_u32("red",red);
}
void read_red(void){
nvs_read_u32("red",&red);
}
void write_green(void){
nvs_write_u32("green",green);
}
void read_green(void){
nvs_read_u32("green",&green);
}
void write_blue(void){
nvs_write_u32("blue",blue);
}
void read_blue(void){
nvs_read_u32("blue",&blue);
}
void write_brightness(void){
nvs_write_u32("brightness",brightness);
}
void read_brightness(void){
nvs_read_u32("brightness",&brightness);
}
void write_light_interval(void){
nvs_write_u32("light_interval",light_interval);
}
void read_light_interval(void){
nvs_read_u32("light_interval",&light_interval);
}
void write_radar_interval(void){
nvs_write_u32("radar_interval",radar_interval);
}
void read_radar_interval(void){
nvs_read_u32("radar_interval",&radar_interval);
}
void write_fade_time(void){
nvs_write_u32("fade_time",fade_time);
}
void read_fade_time(void){
nvs_read_u32("fade_time",&fade_time);
}

View File

@@ -0,0 +1,9 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x4000, encrypted
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 1M,
ota_0, app, ota_0, , 1M,
ota_1, app, ota_1, , 1M,
storage, data, spiffs, , 0x32000, encrypted
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, , 0x4000, encrypted
4 otadata, data, ota, , 0x2000,
5 phy_init, data, phy, , 0x1000,
6 factory, app, factory, , 1M,
7 ota_0, app, ota_0, , 1M,
8 ota_1, app, ota_1, , 1M,
9 storage, data, spiffs, , 0x32000, encrypted

View File

@@ -0,0 +1,119 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "smart_config.h"
#include "common.h"
#include "led.h"
#include "nvs_storage.h"
#include "mqtt.h"
#include "wifi.h"
//FreeRTOS事件组标识什么时候连接成功
static EventGroupHandle_t s_wifi_event_group;
//事件组允许每个事件多个位但是我们只关心一个事件是否成功连接到AP
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig";
static void smartconfig_task(void * parm);
esp_event_handler_instance_t instance_wifi;
esp_event_handler_instance_t instance_ip;
esp_event_handler_instance_t instance_sc;
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) {
xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 10, NULL);
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
ESP_LOGI(TAG, "Scan done");
} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
ESP_LOGI(TAG, "Found channel");
} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
ESP_LOGI(TAG, "Got SSID and password");
smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
wifi_config_t wifi_config;
bzero(&wifi_config, sizeof(wifi_config_t));
//保存wifi信息
memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
wifi_config.sta.bssid_set = evt->bssid_set;
if (wifi_config.sta.bssid_set == true) {
memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
}
memcpy(ssid, evt->ssid, sizeof(evt->ssid));
memcpy(pwd, evt->password, sizeof(evt->password));
ESP_LOGI(TAG, "SSID:%s", ssid);
ESP_LOGI(TAG, "PASSWORD:%s", pwd);
//保存wifi账号和密码
write_ssid();
write_pwd();
ESP_ERROR_CHECK( esp_wifi_disconnect() );
ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK( esp_wifi_connect() );
} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
}
}
//智能配网任务
static void smartconfig_task(void * parm)
{
ESP_LOGI(TAG, "start smart config");
EventBits_t uxBits;
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
while (1) {
uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
if(uxBits & CONNECTED_BIT) {
wifi_status=1;
led_status();
ESP_LOGI(TAG, "WiFi Connected to ap");
}
if(uxBits & ESPTOUCH_DONE_BIT) {
ESP_LOGI(TAG, "smartconfig over");
esp_smartconfig_stop();
vTaskDelete(NULL);
}
//打开mqtt
// mqtt_continue();
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_wifi));
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_ip));
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(SC_EVENT, ESP_EVENT_ANY_ID, instance_sc));
}
}
void smart_config_start(void)
{
ESP_ERROR_CHECK( nvs_flash_init() );
ESP_ERROR_CHECK(esp_netif_init());
s_wifi_event_group = xEventGroupCreate();
wifi_mqtt_stop();
ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, instance_wifi) );
ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, instance_ip) );
ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, instance_sc) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_start());
}

View File

@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAP4LF7E72HakMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTkwNjA3MDk1OTE2WhcNMjAwNjA2MDk1OTE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAlzfCyv3mIv7TlLkObxunKfCdrJ/zgdANrsx0RBtpEPhV560hWJ0fEin0
nIOMpJSiF9E6QsPdr6Q+eogH4XnOMU9JE+iG743N1dPfGEzJvRlyct/Ck8SswKPC
9+VXsnOdZmUw9y/xtANbURA/TspvPzz3Avv382ffffrJGh7ooOmaZSCZFlSYHLZA
w/XlRr0sSRbLpFGY0gXjaAV8iHHiPDYLy4kZOepjV9U51xi+IGsL4w75zuMgsHyF
3nJeGYHgtGVBrkL0ZKG5udY0wcBjysjubDJC4iSlNiq2HD3fhs7j6CZddV2v845M
lVKNxP0kO4Uj4D8r+5USWC8JKfAwxQIDAQABo1AwTjAdBgNVHQ4EFgQU6OE7ssfY
IIPTDThiUoofUpsD5NwwHwYDVR0jBBgwFoAU6OE7ssfYIIPTDThiUoofUpsD5Nww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXIlHS/FJWfmcinUAxyBd
/xd5Lu8ykeru6oaUCci+Vk9lyoMMES7lQ+b/00d5x7AcTawkTil9EWpBTPTOTraA
lzJMQhNKmSLk0iIoTtAJtSZgUSpIIozqK6lenxQQDsHbXKU6h+u9H6KZE8YcjsFl
6vL7sw9BVotw/VxfgjQ5OSGLgoLrdVT0z5C2qOuwOgz1c7jNiJhtMdwN+cOtnJp2
fuBgEYyE3eeuWogvkWoDcIA8r17Ixzkpq2oJsdvZcHZPIZShPKW2SHUsl98KDemu
y0pQyExmQUbwKE4vbFb9XuWCcL9XaOHQytyszt2DeD67AipvoBwVU7/LBOvqnsmy
hA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,164 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "statistic_free_rtos.h"
static char task_names[NUM_OF_SPIN_TASKS][configMAX_TASK_NAME_LEN];
static SemaphoreHandle_t sync_spin_task;
static SemaphoreHandle_t sync_stats_task;
/**
* @brief 函数打印给定时间内任务的CPU使用情况
*
*
* @param xTicksToWait 统计测量周期
*
* @return
* - ESP_OK 成功
* - ESP_ERR_NO_MEM 内存不足,无法分配内部数组
* - ESP_ERR_INVALID_SIZE uxTaskGetSystemState的数组大小不足尝试增加ARRAY_SIZE_OFFSET
* - ESP_ERR_INVALID_STATE 延迟时间太短
*/
static esp_err_t print_real_time_stats(TickType_t xTicksToWait)
{
TaskStatus_t *start_array = NULL, *end_array = NULL;
UBaseType_t start_array_size, end_array_size;
uint32_t start_run_time, end_run_time;
esp_err_t ret;
//分配数组存储当前的任务状态
start_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
start_array = malloc(sizeof(TaskStatus_t) * start_array_size);
if (start_array == NULL) {
ret = ESP_ERR_NO_MEM;
goto exit;
}
//获取当前任务状态
start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time);
if (start_array_size == 0) {
ret = ESP_ERR_INVALID_SIZE;
goto exit;
}
vTaskDelay(xTicksToWait);
//分配数组以存储延迟后的任务状态
end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
end_array = malloc(sizeof(TaskStatus_t) * end_array_size);
if (end_array == NULL) {
ret = ESP_ERR_NO_MEM;
goto exit;
}
//获取延迟后任务状态
end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time);
if (end_array_size == 0) {
ret = ESP_ERR_INVALID_SIZE;
goto exit;
}
//以运行时统计时钟周期为单位,计算合计已用时间
uint32_t total_elapsed_time = (end_run_time - start_run_time);
if (total_elapsed_time == 0) {
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
printf("| Task | Run Time | Percentage\n");
//将开始数组和结束数组的每一个任务进行匹配
for (int i = 0; i < start_array_size; i++) {
int k = -1;
for (int j = 0; j < end_array_size; j++) {
if (start_array[i].xHandle == end_array[j].xHandle) {
k = j;
//通过覆盖他们的句柄来标记已匹配的任务
start_array[i].xHandle = NULL;
end_array[j].xHandle = NULL;
break;
}
}
//检查是否找到匹配的任务
if (k >= 0) {
uint32_t task_elapsed_time = end_array[k].ulRunTimeCounter - start_array[i].ulRunTimeCounter;
uint32_t percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * portNUM_PROCESSORS);
printf("| %s | %d | %d%%\n", start_array[i].pcTaskName, task_elapsed_time, percentage_time);
}
}
//打印不匹配的任务
for (int i = 0; i < start_array_size; i++) {
if (start_array[i].xHandle != NULL) {
printf("| %s | Deleted\n", start_array[i].pcTaskName);
}
}
for (int i = 0; i < end_array_size; i++) {
if (end_array[i].xHandle != NULL) {
printf("| %s | Created\n", end_array[i].pcTaskName);
}
}
ret = ESP_OK;
exit: //公共返回路径
free(start_array);
free(end_array);
return ret;
}
static void spin_task(void *arg)
{
xSemaphoreTake(sync_spin_task, portMAX_DELAY);
while (1) {
//消耗CPU周期
for (int i = 0; i < SPIN_ITER; i++) {
__asm__ __volatile__("NOP");
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
static void stats_task(void *arg)
{
xSemaphoreTake(sync_stats_task, portMAX_DELAY);
//开始所有旋转任务
for (int i = 0; i < NUM_OF_SPIN_TASKS; i++) {
xSemaphoreGive(sync_spin_task);
}
//定期打印实时统计信息
while (1) {
printf("\n\nGetting real time stats over %d ticks\n", STATS_TICKS);
if (print_real_time_stats(STATS_TICKS) == ESP_OK) {
printf("Real time stats obtained\n");
} else {
printf("Error getting real time stats\n");
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void free_rtos_start(void)
{
//允许其他核心完成初始化
vTaskDelay(pdMS_TO_TICKS(100));
//创建信号量以进行同步
sync_spin_task = xSemaphoreCreateCounting(NUM_OF_SPIN_TASKS, 0);
sync_stats_task = xSemaphoreCreateBinary();
//创建旋转任务
for (int i = 0; i < NUM_OF_SPIN_TASKS; i++) {
snprintf(task_names[i], configMAX_TASK_NAME_LEN, "spin%d", i);
xTaskCreatePinnedToCore(spin_task, task_names[i], 1024, NULL, SPIN_TASK_PRIO, NULL, tskNO_AFFINITY);
}
//创建并启动统计任务
xTaskCreatePinnedToCore(stats_task, "stats", 4096, NULL, STATS_TASK_PRIO, NULL, tskNO_AFFINITY);
xSemaphoreGive(sync_stats_task);
}

View File

@@ -0,0 +1,64 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "statistic_perfmon.h"
static const char* TAG = "perfmon";
static void exec_test_function(void *params)
{
for (int i = 0 ; i < 100 ; i++) {
__asm__ __volatile__(" nop");
}
}
// 具有专用性能计数器的表
static uint32_t pm_check_table[] = {
XTPERF_CNT_CYCLES, XTPERF_MASK_CYCLES, // 总周期
XTPERF_CNT_INSN, XTPERF_MASK_INSN_ALL, // 总的说明
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_LOCAL_MEM, // 内存读取
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_LOCAL_MEM, // 内存写入
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_ALL &(~XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP), // 等待其他原因
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP, // 等待注册依赖项
XTPERF_CNT_OVERFLOW, XTPERF_MASK_OVERFLOW, // 最后一个测试周期
};
#define TOTAL_CALL_AMOUNT 200
#define PERFMON_TRACELEVEL -1 // -1将忽略跟踪级别
void perfmon_start(void)
{
ESP_LOGI(TAG, "Start");
ESP_LOGI(TAG, "Start test with printing all available statistic");
xtensa_perfmon_config_t pm_config = {};
pm_config.counters_size = sizeof(xtensa_perfmon_select_mask_all) / sizeof(uint32_t) / 2;
pm_config.select_mask = xtensa_perfmon_select_mask_all;
pm_config.repeat_count = TOTAL_CALL_AMOUNT;
pm_config.max_deviation = 1;
pm_config.call_function = exec_test_function;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = PERFMON_TRACELEVEL;
xtensa_perfmon_exec(&pm_config);
ESP_LOGI(TAG, "Start test with user defined statistic");
pm_config.counters_size = sizeof(pm_check_table) / sizeof(uint32_t) / 2;
pm_config.select_mask = pm_check_table;
pm_config.repeat_count = TOTAL_CALL_AMOUNT;
pm_config.max_deviation = 1;
pm_config.call_function = exec_test_function;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = PERFMON_TRACELEVEL;
xtensa_perfmon_exec(&pm_config);
ESP_LOGI(TAG, "The End");
}

View File

@@ -0,0 +1,201 @@
/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "wifi.h"
#include "common.h"
#include "led.h"
#include "mqtt.h"
#include "http_server.h"
static const char *TAG = "wifi";
static int s_retry_num = 0;
static EventGroupHandle_t s_wifi_event_group;
static esp_event_handler_instance_t instance_any_id;
static esp_event_handler_instance_t instance_got_ip;
// 站点回调函数
static void station_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
printf("station event handler begin \n\n\n");
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
// if (s_retry_num < MAXIMUM_RETRY) {
// esp_wifi_connect();
// s_retry_num++;
// ESP_LOGI(TAG, "retry to connect to the AP");
// } else {
// xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
// }
// ESP_LOGI(TAG,"connect to the AP fail");
} 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;
ESP_LOGI(TAG, "got ip: " IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
// AP回调函数
static void soft_ap_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
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);
} 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);
}
}
//站点模式
static void wifi_station_init(void)
{
esp_netif_create_default_wifi_sta();
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &station_event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &station_event_handler, NULL, &instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = "",
.password = "",
.listen_interval = LISTEN_INTERVAL,
/* 设置密码意味着工作站将连接到包括WEP/WPA在内的所有安全模式。但是这些模式已被弃用不建议使用。
* 如果您的接入点不支持WPA2可以通过在下面的行注释来启用这些模式 */
//.threshold.authmode = WIFI_AUTH_WPA2_PSK,
//PMF功能
.pmf_cfg = {
.capable = true,
.required = false
},
},
};
strcpy((char *)wifi_config.sta.ssid,(char *)ssid);
strcpy((char *)wifi_config.sta.password,(char *)pwd);
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
}
//启动wifi站点模式
void wifi_start(void)
{
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
wifi_station_init();
ESP_ERROR_CHECK(esp_wifi_start());
// 省电模式
esp_wifi_set_ps(POWER_SAVE_MODE);
//STATION模式等待建立连接或者超过连接最大次数后连接失败比特位是通过事件处理程序设置
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",ssid, pwd);
wifi_status=1;
led_status();
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", ssid, pwd);
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
// 停止wifi
void wifi_mqtt_stop(void)
{
if(is_wifi_offline==0){
// 停止mqtt和wifi
mqtt_stop();
esp_wifi_stop();
wifi_status=0;
led_status();
}
}
// 继续wifi站点模式
void wifi_continue(void)
{
ESP_ERROR_CHECK(esp_wifi_start());
//STATION模式等待建立连接或者超过连接最大次数后连接失败比特位是通过事件处理程序设置
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",ssid, pwd);
wifi_status=1;
led_status();
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", ssid, pwd);
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
//启动AP
void ap_start(void)
{
wifi_mqtt_stop();
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
ESP_ERROR_CHECK(esp_netif_init());
esp_netif_create_default_wifi_ap();
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,
&soft_ap_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = AP_SSID,
.ssid_len = strlen(AP_SSID),
.channel = AP_CHANNEL,
.password = AP_PASS,
.max_connection = AP_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(AP_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", AP_SSID, AP_PASS, AP_CHANNEL);
//启动web服务
http_server_start();
}

View File

@@ -0,0 +1,198 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>物美智能设备AP配置</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#all{
margin: 20px auto;
position: relative;
width:320px;
text-align:center;
}
#all #tab li{
list-style: none;
float: left;
width: 94px;
line-height: 40px;
text-align: center;
font-size: 16px;
color:#fff;
margin-left:10px;
}
#tab{
height:40px;
}
#all .con{
border:1px solid #ddd;
padding:10px;
margin:15px 10px;
}
.group{
line-height:50px;
}
.group .btn{
padding:4px 14px;
background:#f56c6c;
color:#fff;
border:1px solid #ddd;
border-radius:6px;
width:190px;
}
.group span{
width:85px;
display:inline-block;
font-size:14px;
}
.group input{
line-height:24px;
width:180px;
}
</style>
<script type="text/javascript">
window.onload = function(){
var tab = document.getElementById("tab");
var lis = tab.getElementsByTagName('li');//获得标签li的数组
var cons = document.getElementsByClassName('con');//获得下面内容div的数组
for(var i=0;i<lis.length;i++){
lis[i].num = i;//给对象添加属性,赋值用于标记
lis[i].onclick = function(){
if(this.num==2){
window.location.href="/download/";
}
//tab内容显示和隐藏
for(var j = 0;j<cons.length;j++){
if(j==this.num){
cons[this.num].style.display = 'block';
}else{
cons[j].style.display = 'none';
}
}
//设置选中
for(var k=0;k<lis.length;k++){
if(k==this.num){
lis[this.num].style.backgroundColor ="#006DFE"; //设置为选中
}else{
lis[k].style.backgroundColor="#888"; //设置背景为灰色
}
}
}
}
// 根据url参数设置选中
var value=getQueryVariable("tab");
console.log("value",value);
if(value==0){
lis[0].onclick();
}else if(value==1){
lis[1].onclick();
}
}
function getQueryVariable(variable){
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
function wifiSubmit(){
var ssid = document.getElementById("ssid").value;
var password = document.getElementById("password").value;
var uuid = document.getElementById("uuid").value;
if(ssid=="" || password=="" || uuid==""){
alert("WIFI的名称、密码和关联用户不能为空。")
return;
}else{
// 确认提交
}
var button = document.getElementById("wifi_submit").submit();
}
function mqttSubmit(){
var mqtt_address = document.getElementById("mqtt_address").value;
var mqtt_port = document.getElementById("mqtt_port").value;
if(mqtt_address=="" || mqtt_port==""){
alert("MQTT的地址和端口不能为空");
return;
}else{
//确认提交
}
var button = document.getElementById("mqtt_submit").submit();
}
</script>
</head>
<body>
<div style="width:100%;height:60px;font-size:22px;line-height:60px;background:#006DFE;color:#fff;text-align:center;">物美智能设备配置</div>
<div id="all">
<ul id="tab">
<li style="background: #006DFE;">服务端</li>
<li style="background: #888;">配网</li>
<li style="background: #888;">上传证书</li>
</ul>
<div class="con" style="display:block;">
<form name=”form1” method="post" action="mqtt" id="mqtt_submit">
<div class="group">
<span>MQTT地址</span>
<input type="text" name="mqtt_address" placeholder="www.wumei.live" id="mqtt_address">
</div>
<div class="group">
<span>MQTT端口</span>
<input type="text" name="mqtt_port" placeholder="1883" id="mqtt_port">
</div>
<div class="group">
<span>MQTT账号</span>
<input type="text" name="mqtt_account" placeholder="可选项">
</div>
<div class="group">
<span>MQTT密码</span>
<input type="text" name="mqtt_password" placeholder="可选项">
</div>
<div style="line-height:50px;">
<span>使用证书:</span>
<input type="radio" name="is_certifi" id="unuse" value=0 checked> <label for="unuse" style="margin-right:20px;">不使用</label>
<input type="radio" name="is_certifi" id="use" value=1> <label for="use" style="margin-right:35px;">使用</label><br/>
</div>
<div style="line-height:20px;" class="group">
<span></span>
<input type="button" class="btn" value="连接服务端" onclick="mqttSubmit()">
</div>
</form>
</div>
<div class="con" style="display:none;">
<form name=”form2” method="post" action="wifi" id="wifi_submit">
<div class="group">
<span>WIFI名称</span>
<input type="text" name="ssid" placeholder="不能包含中文" id="ssid">
</div>
<div class="group">
<span>WIFI密码</span>
<input type="text" name="password" placeholder="不能包含中文" id="password">
</div>
<div class="group">
<span>关联用户:</span>
<input type="text" name="uuid" placeholder="用户ID或者手机号" id="uuid">
</div>
<div style="line-height:20px;" class="group">
<span></span>
<input type="button" class="btn" value="配网" onclick="wifiSubmit()" >
</div>
</form>
</div>
<div class="con"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,55 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>物美智能设备AP配置</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#main{
margin: 20px auto;
position: relative;
width:320px;
height:200px;
border:1px solid #ccc;
border-radius:5px;
text-align:center;
}
.header{
width:320px;
line-height:32px;
font-size:18px;
background:#006DFE;
color:#fff;
}
.content span{
line-height:130px;
}
.content a{
position:absolute;
bottom:10px;
width:90px;
right:10px;
font-size:14px;
text-decoration:none;
}
</style>
</head>
<body>
<div style="width:100%;height:60px;font-size:22px;line-height:60px;background:#006DFE;color:#fff;text-align:center;">物美智能设备配置</div>
<div id="main">
<div class="header">-- 温馨提示 --</div>
<div class="content">
<span>配置已经完成,请重新启动设备。</span>
<a href="/" target="_self">返回主页 >></a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,103 @@
<style type="text/css">
*{margin: 0;padding: 0;}
#all{margin: 20px auto;position: relative;width:320px;text-align:center;}
#all #tab li{list-style: none;float: left;width: 94px;line-height: 40px;text-align: center;font-size: 16px;color:#fff;margin-left:10px;}
#tab{ height:40px;}
#all .con{border:1px solid #aaa;padding:10px;margin:15px 10px;}
#list{margin: 20px auto;position:relative;width:300px;text-align:center;}
#list table{border-collapse:collapse;border:none;width:300px;}
#list table tr td{border:solid#aaa 1px;padding:10px;}
</style>
<div style="width:100%;height:60px;font-size:22px;line-height:60px;background:#006DFE;color:#fff;text-align:center;">物美智能设备配置</div>
<div id="all">
<ul id="tab">
<li style="background: #888;">服务端</li>
<li style="background: #888;">配网</li>
<li style="background: #006DFE;">上传证书</li>
</ul>
<div class="con" style="display:block;">
<table class="fixed" border="0">
<col width="1000px" /><col width="500px" />
<tr><td>
<table border="0">
<tr style="height:50px;">
<td>
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
</td>
</tr>
<tr>
<input id="filepath" type="hidden" style="width:100%;">
<td>
<button style="margin:10px 0;padding:6px 14px;background:#f56c6c;color:#fff; border:1px solid #ddd;border-radius:6px;width:270px;" id="upload" type="button" onclick="upload()" style="padding:0 10px;">上传</button>
</td>
</tr>
</table>
</td></tr>
</table>
</div>
</div>
<script>
window.onload = function(){
var tab = document.getElementById("tab");
var lis = tab.getElementsByTagName('li');//获得标签li的数组
var cons = document.getElementsByClassName('con');//获得下面内容div的数组
for(var i=0;i<lis.length;i++){
lis[i].num = i;//给对象添加属性,赋值用于标记
lis[i].onclick = function(){
if(this.num==0 ){
window.location.href="/?tab=0";
}
if(this.num==1){
window.location.href="/?tab=1";
}
}
}
}
function setpath() {
var default_path = document.getElementById("newfile").files[0].name;
document.getElementById("filepath").value = default_path;
}
function upload() {
var filePath = document.getElementById("filepath").value;
var upload_path = "/upload/" + filePath;
var fileInput = document.getElementById("newfile").files;
/* 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";
if (fileInput.length == 0) {
alert("No file selected!");
} else if (filePath.length == 0) {
alert("File path on server is not set!");
} else if (filePath.indexOf(' ') >= 0) {
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 {
document.getElementById("newfile").disabled = true;
document.getElementById("filepath").disabled = true;
document.getElementById("upload").disabled = true;
var file = fileInput[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.open();
document.write(xhttp.responseText);
document.close();
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
location.reload()
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
location.reload()
}
}
};
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
</script>