#include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_log.h" #include "esp_system.h" #include "freertos/event_groups.h" #include "esp_timer.h" #include "esp_err.h" #include "user_config.h" #include "LED.h" #include "list.h" #include "freertos/timers.h" #include "user_sleep.h" #include "esp_sleep.h" #include "esp_sleep.h" #include "user_time.h" #include "driver/uart.h" #include "driver/rtc_io.h" char user_device_id[50] = {0}; RTC_FAST_ATTR unsigned char power = 0; #define MAX_RETRY_ACK 3 // 最大重传次数停止发送数据 int retry_times = 0; bool powerOn_flag = false; static const char *LOG_TAG = "user_main"; extern Node *Send_list; // 发送数据链表 YC_DATA_T yc_data; // ListNode *list_head = NULL; adc_oneshot_unit_handle_t adc1_handle; QueueHandle_t screen_queue; QueueHandle_t lora_data_queue; QueueHandle_t yc_data_queue; QueueHandle_t button_Data_queue; EventGroupHandle_t screen_event; extern QueueHandle_t lora_receiveQueue; // lora底层数据上报 extern QueueHandle_t lora_dealhandle; // 开始处理逻辑的数据 QueueHandle_t sleep_queue; QueueHandle_t wakeup_queue; QueueHandle_t Send_Data_queue; // 发送链表任务 // SemaphoreHandle_t button_semaphore; // 刷新屏幕时都得加上按键互斥锁 // SemaphoreHandle_t screen_semaphore; //刷新屏幕时都得加上互斥锁 #if !HARDWARE_SPI struct EPD_INFO_SET left_screen = {}; struct EPD_INFO_SET right_screen = {}; #endif extern LORA_DATA_T lora_data; extern TERMINAL_INFO_T terminal_info; #include "y_ringbuf.h" extern struct RINGBUF_st; extern RINGBUF_st *lora_ringbuf; // static void board_init(void); // static void info_init(void); // static void left_screen_task(void* arg); // static void right_screen_task(void* arg); static void screen_task(void *arg); static void unpack_task(void *arg); static void lora_task(void *arg); static void button_task(void *arg); static void business_logic_task(void *arg); static void gui_task(void *pvParameter); void read_deal_data_callback_handler(); // void Sendlist_task_callback_handler(); void uart_task_callback_handler(); /********************************************************************************* * function : user_nvs_init * Description : 添加NVS相关 获取出厂设备ID等相关参数 * Input : * Output : * Author : Data : 2023 11.08 **********************************************************************************/ void user_nvs_init() { #include "nvs_flash.h" #include "nvs.h" nvs_handle_t my_handle; esp_err_t ret; /* Initialize NVS. */ 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(); printf("nvs_flash_init ok\r\n"); } ret = ESP_OK; if ((ret = nvs_flash_init_partition("nvs")) != ESP_OK) { printf("nvs init fail\r\n"); } else { printf("nvs init ok\r\n"); } ret = nvs_open_from_partition("nvs", "user_config", NVS_READONLY, &my_handle); if (ret != ESP_OK) { printf("nvs_open failed with\r\n"); } size_t len = 0; char cid[50] = {0}; // size_t required_size; // nvs_get_str(my_handle, "server_name", NULL, &required_size); // char* server_name = malloc(required_size); // nvs_get_str(my_handle, "server_name", server_name, &required_size); ret = nvs_get_str(my_handle, "deviceid", NULL, &len); char *result = malloc(len); nvs_get_str(my_handle, "deviceid", result, &len); switch (ret) { case ESP_OK: // printf("Read string from NVS: %s\r\n", cid); break; case ESP_ERR_NVS_NOT_FOUND: printf("Value not found in NVS"); break; default: printf("Error (%d) reading from NVS", ret); } memcpy(user_device_id, cid, len); memcpy(Machine_info.cid, cid, len); #if 1 strcpy((char *)Machine_info.cid, result); printf("device id %s,result = %s,len = %d\r\n", cid, result, len); #else strcpy((char *)Machine_info.cid, "1tpmQwHNS"); #endif printf("Machine_info cid %s\r\n", Machine_info.cid); nvs_close(my_handle); free(result); } extern void app_init(); Machine_info_t default_info = { .left_display_mode = 0, .left_state = 1, .paired = 0, // 未配网 .power_status = 0, // 关机 // .is_setting = 0, //设置模式 .eflagID = 0xFF, .left_max_Quick_refresh_time = 5, // 最大快刷次数 .left_current_Quick_refresh_time = 0, // 当前已经快刷的次数 当前快刷的次数大于设置 慢刷一次 .lora_factory_channel = LORA_CHANENL, .right_max_Quick_refresh_time = 5, // 最大快刷次数 .right_current_Quick_refresh_time = 0, // 当前已经快刷的次数 当前快刷的次数大于设置 慢刷一次 .current_button.button_info = 0x01, // 初始化为1(运行) .last_button.button_info = 0x01, .terminal_name = {0xD2, 0xCF, 0xB3, 0xB2, 0xD6, 0xD5, 0xB6, 0xCB, 0x00, 0x00}, // 蚁巢终端 .terminal_number = {0xD2, 0xCF, 0xB3, 0xB2, 0xB1, 0xE0, 0xBA, 0xC5, 0x00, 0x00}, // 蚁巢编号 .station_name = {0xB9, 0xA4, 0xD5, 0xBE, 0xC3, 0xFB, 0xB3, 0xC6, 0x00, 0x00}, // 工站名称 .station_number = {0xB9, 0xA4, 0xD5, 0xBE, 0xB1, 0xE0, 0xBA, 0xC5, 0x00, 0x00}, // 工站编号 .rssi = 0x64, .refresh_cycle = 2, .batt_precent = 100, .btn_operation = {0xd4, 0xcb, 0xd0, 0xd0, 0x00, 0x00}, .btn_breakDown_info = {0xb9, 0xca, 0xd5, 0xcf, 0x00, 0x00}, .btn_shutDown_info = {0xcd, 0xa3, 0xbb, 0xfa, 0x00, 0x00}, .btn_safeKeep_info = {0xb7, 0xe2, 0xb4, 0xe6, 0x00, 0x00}, .btn_upKeep_info = {0xb1, 0xa3, 0xd1, 0xf8, 0x00, 0x00}, .btn_waitMaterials_info = {0xb4, 0xfd, 0xc1, 0xcf, 0x00, 0x00}, .btn_dis_flag = {true, true, true, true, true, true}, .checkIn_set[0] = { .other_name = {0xC9, 0xFA, 0xB2, 0xFA, 0x00, 0x00}, .checkIn_close = false, }, .checkIn_set[1] = { .other_name = {0xCE, 0xAC, 0xD0, 0xDE, 0x00, 0x00}, .checkIn_close = false, }, .checkIn_set[2] = { .other_name = {0xD1, 0xB2, 0xBC, 0xEC, 0x00, 0x00}, .checkIn_close = false, }, .checkIn_set[3] = { .other_name = {0xB1, 0xA3, 0xD1, 0xF8, 0x00, 0x00}, .checkIn_close = false, }, .person[0] = { .Charge_close = false, .other_name = {0xb9, 0xdc, 0x20, 0x20, 0xc0, 0xed, 0x20, 0x20, 0xd4, 0xb1, 0x3a, 0x00, 0x00, 0x00}, }, .person[1] = { .Charge_close = false, .other_name = {0xc9, 0xfa, 0xb2, 0xfa, 0xd4, 0xf0, 0xc8, 0xce, 0xc8, 0xcb, 0x3a, 0x00, 0x00, 0x00}, }, .person[2] = { .Charge_close = false, .other_name = {0xce, 0xac, 0xd0, 0xde, 0xd4, 0xf0, 0xc8, 0xce, 0xc8, 0xcb, 0x3a, 0x00, 0x00, 0x00}, }, .person[3] = { .Charge_close = false, .other_name = {0xb1, 0xa3, 0xd1, 0xf8, 0xd4, 0xf0, 0xc8, 0xce, 0xc8, 0xcb, 0x3a, 0x00, 0x00, 0x00}, }, .person[4] = { .Charge_close = false, .other_name = {0xd1, 0xb2, 0xbc, 0xec, 0xd4, 0xf0, 0xc8, 0xce, 0xc8, 0xcb, 0x3a, 0x00, 0x00, 0x00}, }, }; #define PRINT_SPIFFS 0 #if PRINT_SPIFFS void printHexData(const void *ptr, size_t size) { const unsigned char *p = (const unsigned char *)ptr; for (size_t i = 0; i < size; ++i) { printf("%02x ", p[i]); if (i % 16 == 0) { printf("\r\n"); } } // printf("\n"); } #endif void app_init() { #if 0 gpio_reset_pin(4); gpio_config_t io_conf = {}; io_conf.pin_bit_mask = (1<<4); io_conf.mode = GPIO_MODE_INPUT; io_conf.pull_up_en = false; gpio_config(&io_conf); while(1) { printf("power gpio is %s\r\n",gpio_get_level(4)?"high":"low"); vTaskDelay(100 / portTICK_PERIOD_MS); } #endif // 设置蜂鸣器声音 #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE beep_init(); #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE font_init(); #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE epd_init(); #endif user_sleep_into(); // 休眠定时器初始化 // charge_init(); // decection_charging_init(); screen_queue = xQueueCreate(25, sizeof(Screen_dis_t)); lora_data_queue = xQueueCreate(20, sizeof(LORA_DATA_T)); yc_data_queue = xQueueCreate(20, sizeof(int)); button_Data_queue = xQueueCreate(10, sizeof(uint8_t)); // screen_semaphore = xSemaphoreCreateMutex(); screen_event = xEventGroupCreate(); // button_semaphore = xSemaphoreCreateMutex(); #if 0 lora_receiveQueue = xQueueCreate(100, sizeof(int)); #else lora_dealhandle = xQueueCreate(100, sizeof(int)); #endif sleep_queue = xQueueCreate(10, sizeof(uint8_t)); // Send_Data_queue= xQueueCreate(10, sizeof(uint8_t)); //发送缓存数据任务 if (sleep_queue != NULL) { // 创建队列成功,myQueue 包含有效的队列句柄 // 在这里可以继续使用该队列 } else { // 创建队列失败,myQueue 是 NULL // 需要处理创建失败的情况 printf("---------------create fail-----------------\r\n"); } wakeup_queue = xQueueCreate(10, sizeof(uint8_t)); if (wakeup_queue != NULL) { // 创建队列成功,myQueue 包含有效的队列句柄 // 在这里可以继续使用该队列 } else { // 创建队列失败,myQueue 是 NULL // 需要处理创建失败的情况 printf("---------------create fail-----------------\r\n"); } extern unsigned char *last_paint_buf_left; extern unsigned char *last_paint_buf_right; extern uint32_t display_size; #if 0 extern unsigned char *tmp_paint_buf; tmp_paint_buf = heap_caps_malloc(display_size,MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM); // 开辟 结构体句柄 所需要的空间 if(tmp_paint_buf!=NULL) { //printf("tmp_paint_buf malloc success\r\n"); }else { printf("tmp_paint_buf malloc fail\r\n"); heap_caps_free(tmp_paint_buf); } #endif #if 1 last_paint_buf_left = heap_caps_malloc(display_size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 开辟所需要的空间 if (last_paint_buf_left != NULL) { // printf("last_paint_buf_left malloc success\r\n"); } else { printf("last_paint_buf_left malloc fail\r\n"); heap_caps_free(last_paint_buf_left); } last_paint_buf_right = heap_caps_malloc(display_size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 开辟所需要的空间 if (last_paint_buf_right != NULL) { // printf("last_paint_buf_right malloc success\r\n"); } else { printf("last_paint_buf_right malloc fail\r\n"); heap_caps_free(last_paint_buf_right); } #endif int reson = esp_sleep_get_wakeup_cause(); // 获取当前唤醒原因 if (reson == ESP_SLEEP_WAKEUP_EXT1) { adc1_init(); // extern void dis_right_instructions(); // dis_right_instructions(); set_screen_dis_info_and_send_queue(true, false, false, false, 100); int power_key = 0; int charge_key = 0; int value_count = 0; charge_key = gpio_get_level(2); printf("charge_key is %s\r\n", !charge_key ? "charge in" : "charge out"); printf("charge_key is %s\r\n", !charge_key ? "charge in" : "charge out"); printf("charge_key is %s\r\n", !charge_key ? "charge in" : "charge out"); printf("charge_key is %s\r\n", !charge_key ? "charge in" : "charge out"); Machine_info.batt_precent = read_battery_voltage(); Machine_info.last_batt_precent = Machine_info.batt_precent; screen_dis_info.is_left = false; while (1) { // value++; charge_key = gpio_get_level(2); if (!charge_key) // 充电中 { Machine_info.batt_precent = read_battery_voltage(); if (Machine_info.batt_precent < 96) { user_compare_power_off(Machine_info.last_batt_precent, Machine_info.batt_precent); printf("charge_key is %s,batt=%d,last batt=%d\r\n", !charge_key ? "charge in" : "charge out", Machine_info.batt_precent, Machine_info.last_batt_precent); value_count++; if (value_count > 60) { Machine_info.last_batt_precent = Machine_info.batt_precent; value_count = 0; } } } else // 未充电 { printf("charge_key is %s\r\n", !charge_key ? "charge in" : "charge out"); // extern void dis_right_instructions(); // dis_right_instructions(); set_screen_dis_info_and_send_queue(true, false, false, false, 100); printf("start power off\r\n"); uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); #if 1 // 电源按键 // adc_oneshot_del_unit(adc1_handle); gpio_reset_pin(4); int ext_wakeup_pin_0 = 4; printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0); ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 0)); // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep. // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs. // No need to keep that power domain explicitly, unlike EXT1. ESP_ERROR_CHECK(rtc_gpio_pullup_en(ext_wakeup_pin_0)); ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(ext_wakeup_pin_0)); gpio_reset_pin(2); const int ext_wakeup_pin_1 = 2; const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; printf("Enabling EXT1 wakeup on pins GPIO%d\r\n", ext_wakeup_pin_1); ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW)); #endif esp_deep_sleep_start(); break; } vTaskDelay(1000 / portTICK_PERIOD_MS); } } // xTaskCreate( left_screen_task, "left_screen_task", 25*1024, NULL, configMAX_PRIORITIES - 1, NULL); // idf.py 设置分区 spiffs_init(); extern uint32_t ulp_wakeup_result; if ( (reson != ESP_SLEEP_WAKEUP_EXT0) && (reson != ESP_SLEEP_WAKEUP_ULP) && (reson != ESP_SLEEP_WAKEUP_TIMER)) { #if PRINT_SPIFFS printHexData(&default_info, sizeof(Machine_info_t)); // spiffs_write(&default_info); #endif spiffs_read_powerOn(&Machine_info); // 重新初始化开机后默认关机 Machine_info.power_status = 0; user_nvs_init(); } if (reson == ESP_SLEEP_WAKEUP_EXT0) { #if 0 adc1_init(); int value = 0; while(1) { value++; adc_read_left_key_pin(adc1_handle); vTaskDelay(10 / portTICK_PERIOD_MS); if(value>10) { break; } } #else int power_key = 0; adc1_init(); while (1) { // value++; power_key = gpio_get_level(4); vTaskDelay(4000 / portTICK_PERIOD_MS); if (0 == gpio_get_level(4)) { if (read_battery_voltage() < 10) // 判断电压小于10% 不让开机 { printf("start power off\r\n"); uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); #if 1 // 电源按键 // adc_oneshot_del_unit(adc1_handle); gpio_reset_pin(4); int ext_wakeup_pin_0 = 4; printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0); ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 0)); // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep. // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs. // No need to keep that power domain explicitly, unlike EXT1. ESP_ERROR_CHECK(rtc_gpio_pullup_en(ext_wakeup_pin_0)); ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(ext_wakeup_pin_0)); gpio_reset_pin(2); const int ext_wakeup_pin_1 = 2; const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; printf("Enabling EXT1 wakeup on pins GPIO%d\r\n", ext_wakeup_pin_1); ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW)); #endif esp_deep_sleep_start(); } adc_oneshot_del_unit(adc1_handle); // 删除adc使用 uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); #if 1 // USER_DEEP_SLEEP_ENABLE reson = is_wake_up_reson(); // 返回唤醒的原因 ESP_LOGW(LOG_TAG, "power on- reson = %d\r\n", reson); /* ULP Risc-V read and detected a temperature above the limit */ if (reson == ESP_SLEEP_WAKEUP_EXT0) { if (Machine_info.power_status == 0) { Machine_info.power_status = 1; // 开机 lora_set_power_level(1); // 打开lora电源 // 恢复串口i功能 uart_sleep_out_config(); beep_blink(1000, 1); Machine_info.left_current_Quick_refresh_time = 5; vTaskDelay(1000 / portTICK_PERIOD_MS); // printf("开机刷屏\r\n"); // if(xQueueSend(screen_queue,&Machine_info,portMAX_DELAY) != true) // { // printf("left send fail\r\n"); // } } else if (Machine_info.power_status == 1) { printf("aready power on\r\n"); } } #endif break; } else { printf("start power off\r\n"); uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); #if 1 // 电源按键 // adc_oneshot_del_unit(adc1_handle); gpio_reset_pin(4); int ext_wakeup_pin_0 = 4; printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0); ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 0)); // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep. // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs. // No need to keep that power domain explicitly, unlike EXT1. ESP_ERROR_CHECK(rtc_gpio_pullup_en(ext_wakeup_pin_0)); ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(ext_wakeup_pin_0)); gpio_reset_pin(2); const int ext_wakeup_pin_1 = 2; const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; printf("Enabling EXT1 wakeup on pins GPIO%d\r\n", ext_wakeup_pin_1); ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW)); #endif esp_deep_sleep_start(); } } #endif printf("deep Wake up from ext0\n"); } else if (reson == ESP_SLEEP_WAKEUP_ULP) { printf("wakeup_result = %ld\r\n", ulp_wakeup_result); // int key = find_key_value(ulp_wakeup_result); // printf("key = %d\r\n",key); #if 1 // reson = is_wake_up_reson(); //返回唤醒的原因 /* ULP Risc-V read and detected a temperature above the limit */ if (reson == ESP_SLEEP_WAKEUP_ULP) { if (Machine_info.power_status == 0) { printf("left key press power off\r\n"); uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); #if 1 font_into_sleep(); #include "EPD.h" epd_sleep(SCREEN_LEFT); epd_sleep(SCREEN_RIGHT); // gpio_hold_en(PIN_L_CS); // gpio_hold_en(PIN_R_CS); // gpio_set_level(PIN_L_CS,1); // gpio_set_level(PIN_R_CS,1); // gpio_reset_pin(46); // uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); // ESP_ERROR_CHECK(uart_wait_tx_done(UART_NUM_1,portMAX_DELAY)); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); // gpio_set_level(LORA_TXD_PIN, 0); // gpio_set_level(LORA_RXD_PIN, 0); // uart_sleep_in_config(); uart_driver_delete(UART_NUM_1); gpio_reset_pin(LORA_TXD_PIN); gpio_reset_pin(LORA_RXD_PIN); gpio_config_t io_conf = {}; io_conf.pin_bit_mask = (1 << LORA_TXD_PIN); io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pull_up_en = false; gpio_config(&io_conf); io_conf.pin_bit_mask = (1 << LORA_RXD_PIN); io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pull_up_en = false; gpio_config(&io_conf); gpio_set_level(LORA_TXD_PIN, 0); gpio_set_level(LORA_RXD_PIN, 0); gpio_hold_en(LORA_TXD_PIN); gpio_hold_en(LORA_RXD_PIN); // 电源按键 // adc_oneshot_del_unit(adc1_handle); gpio_reset_pin(4); int ext_wakeup_pin_0 = 4; // printf("Enabling EXT0 wakeup on pin GPIO%d\n", ext_wakeup_pin_0); ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(ext_wakeup_pin_0, 0)); // Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep. // EXT0 resides in the same power domain (RTC_PERIPH) as the RTC IO pullup/downs. // No need to keep that power domain explicitly, unlike EXT1. ESP_ERROR_CHECK(rtc_gpio_pullup_en(ext_wakeup_pin_0)); ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(ext_wakeup_pin_0)); // 充电按键 gpio_reset_pin(2); const int ext_wakeup_pin_1 = 2; const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; printf("Enabling EXT1 wakeup on pins GPIO%d\r\n", ext_wakeup_pin_1); ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW)); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup()); #endif esp_deep_sleep_start(); } else { int btn = left_adc_wake_btn_send(); ESP_LOGE(LOG_TAG, "btn = %d", btn); Machine_info.left_state = btn; beep_blink(30, 1); #if 1 set_screen_dis_info_and_send_queue(true, true, false, false, 100); #endif while (1) { vTaskDelay(20 / portTICK_PERIOD_MS); } } } #endif } #if 0 // info_init(); // board_init(); #else #if USER_DEEP_SLEEP_ENABLE int reson = is_wake_up_reson(); // 返回唤醒的原因 printf(" info_init reson = %d\r\n", reson); // idf.py 设置分区 spiffs_init(); /* not a wakeup from ULP, load the firmware */ if ((reson != ESP_SLEEP_WAKEUP_ULP) && (reson != ESP_SLEEP_WAKEUP_TIMER)) { #if 1 // uint8_t yc_name[6] = {0xd2,0xcf,0xb3,0xb2,0x00,0x00}; Machine_info_t default_info = { .left_display_mode = 0, //.left_state =1, .eflagID = 0xFF, .rssi = 0x64, .refresh_cycle = 2, .batt_precent = 100, }; spiffs_write(&default_info); #endif spiffs_read(&Machine_info); } else { } #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE lora_init(); #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE adc1_init(); #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE button_init(adc1_handle); // 左侧按键 power_button_init(adc1_handle); // 右侧电源按键 Machine_info.batt_precent = read_battery_voltage(); Machine_info.last_batt_precent = Machine_info.batt_precent; #endif #if USER_NOT_SLEEP_ENABLE || USER_LIGHT_SLEEP_ENABLE || USER_DEEP_SLEEP_ENABLE // timer_init(); #endif ////////////////////////////////////////////////////////////////////////////////////////////////// #endif xTaskCreate(button_task, "button_task", 5 * 2048, NULL, configMAX_PRIORITIES, NULL); // xTaskCreate( right_screen_task, "right_screen_task",15*1024, NULL, configMAX_PRIORITIES - 2, NULL); xTaskCreate(screen_task, "screen_task", 40 * 1024, NULL, configMAX_PRIORITIES - 2, NULL); printf("=================================UPDATE OK===========================\r\n"); #if 1 xTaskCreate(business_logic_task, "business_logic_task", 25 * 1024, NULL, YC_TASK_NONE, NULL); // xTaskCreate( unpack_task, "unpack_task", 5*1024, NULL, YC_TASK_UNPACK, NULL); #if !USER_QIXIN // xTaskCreate(lora_task, "lora_task", 5 * 1024, NULL, configMAX_PRIORITIES, NULL); #endif #if 0 xTaskCreate(gui_task, "gui_task", 4096 * 2, NULL, 5, NULL); #endif #if 1 // 任务处理函数 xTaskCreate(read_deal_data_callback_handler, "read_deal_data_task", 1024 * 8, NULL, configMAX_PRIORITIES, NULL); #endif // 添加定时发送当前是否有链表数据 // xTaskCreate(Sendlist_task_callback_handler, "Sendlist_task", 1024*8, NULL, configMAX_PRIORITIES, NULL); #endif // 打印系统信息 print_systenInfo(); } static void screen_task(void *arg) { Machine_info.rssi = 100; // 没有获取到真数据,默认100 int reson = is_wake_up_reson(); // 返回唤醒的原因 ESP_LOGW(LOG_TAG, "screen_task %d", reson); if ((reson != ESP_SLEEP_WAKEUP_ULP) && (reson != ESP_SLEEP_WAKEUP_TIMER) && (reson != ESP_SLEEP_WAKEUP_EXT0)) { // Paint_leftScreen_main_powerOn(); // Paint_rightScreen_main_powerON(); Paint_leftScreen(Machine_info.power_status, false); Paint_rightScreen(Machine_info.power_status, false); } else if (reson == ESP_SLEEP_WAKEUP_EXT0) { // 按键从深睡唤醒,开机刷新屏慕 ESP_LOGW(LOG_TAG, "按键从深睡唤醒,开机刷新屏慕"); // Paint_leftScreen_main_slow(&Machine_info); // Paint_rightScreen_main_slow(&Machine_info); Paint_leftScreen(Machine_info.power_status, false); Paint_rightScreen(Machine_info.power_status, false); } Screen_dis_t screen_rev_info; screen_rev_info.is_left = false; screen_rev_info.is_into_sleep = true; while (1) { if (xQueueReceive(screen_queue, &screen_rev_info, (TickType_t)portMAX_DELAY)) { ESP_LOGW(LOG_TAG, "screen_rev_info==>%s , %s ,%s ,%s", screen_rev_info.is_left ? "left refreshing" : "right refreshing", screen_rev_info.is_into_sleep ? "into sleep" : "not sleep", screen_rev_info.is_change_power ? "change power" : "not change power", screen_rev_info.is_dont_dis ? "dont dis" : "dis"); if (screen_rev_info.is_dont_dis) { ESP_LOGE(LOG_TAG, "goto -> dont_dis"); goto dont_dis; } font_exit_sleep(); if (screen_rev_info.is_left) // 刷左屏 { if (Machine_info.left_current_Quick_refresh_time >= Machine_info.left_max_Quick_refresh_time) { Machine_info.left_current_Quick_refresh_time = 0; Paint_leftScreen(Machine_info.power_status, false); } else { Machine_info.left_current_Quick_refresh_time++; Paint_leftScreen(Machine_info.power_status, true); } } else // 刷右屏 { if (Machine_info.right_current_Quick_refresh_time == 0) { Machine_info.right_current_Quick_refresh_time = 1; Paint_rightScreen(Machine_info.power_status, true); } else { Paint_rightScreen(Machine_info.power_status, false); } } dont_dis: // ESP_LOGE(LOG_TAG, "%d %d %d", Machine_info.power_status, Machine_info.paired, screen_rev_info.is_into_sleep); if ((Machine_info.power_status == 1) && (Machine_info.paired == 1) && screen_rev_info.is_into_sleep) { ESP_LOGD(LOG_TAG, "100ms sleep %s", screen_rev_info.is_left ? "left" : "right"); if (screen_rev_info.is_change_power) { ESP_LOGE(LOG_TAG, "=============power_status %s======== set power off", Machine_info.power_status ? "is power on" : "is power off"); Machine_info.power_status = 0; // 关机 } sleep_timer_start(screen_rev_info.sleep_ms); // 进入睡眠 } if (Machine_info.power_status == 0) // 展示说明书都是先左后右,等右屏刷完再休眠 { sleep_timer_start(1000); // 进入睡眠 } } } } static void button_task(void *arg) { // update_last_button_info(Machine_info.current_button.button_info);//初始化上个按键为运行,用作paint0703计时 uint8_t button_info; while (1) { if (xQueueReceive(button_Data_queue, &button_info, (TickType_t)portMAX_DELAY)) { #if 1 ESP_LOGI(LOG_TAG, "btn_flag[%d][%d][%d][%d][%d][%d],button_info = [%d]%s ", Machine_info.btn_dis_flag[0], Machine_info.btn_dis_flag[1], Machine_info.btn_dis_flag[2], Machine_info.btn_dis_flag[3], Machine_info.btn_dis_flag[4], Machine_info.btn_dis_flag[5], button_info, Machine_info.power_status ? "poweron" : "poweroff"); ESP_LOGI(LOG_TAG, "batt_precent[%d]\ncid[%s]\nlast_button[%d]\nlora_new_channel[%d]\neflagID[%d]\nDuration_time[%ld]rssi[%d]paired[%s]", Machine_info.batt_precent, Machine_info.cid, Machine_info.last_button.button_info, Machine_info.lora_new_channel, Machine_info.eflagID, Machine_info.Duration_time, Machine_info.rssi, Machine_info.paired ? "paired" : "not pair"); // print_lora_set_info(); #endif if (button_info < 0x12) // 左屏慕按键 { // vTaskDelay(200/ portTICK_PERIOD_MS); // print_lora();//按键查询lora配置 if (Machine_info.btn_dis_flag[button_info - 1] == false) { printf("btn is close\n"); button_info = STATE_OPERATION; // 按键关闭,默认运行 if ((Machine_info.power_status == 1) && (Machine_info.paired == 1)) { set_screen_dis_info_and_send_queue(false, false, false, true, 100); // sleep_timer_start(100); // 进入睡眠 } } Machine_info.current_button.button_info = button_info; // 判断当前的按键状态 设置为当前状态后 再次按键不处理 printf("last btn = %d ,curr btn = %d\n", Machine_info.last_button.button_info, Machine_info.current_button.button_info); if (Machine_info.last_button.button_info != Machine_info.current_button.button_info) { if (Machine_info.paired == 1) { // printf("paired add data to list chanl = 0x%02x\r\n",Machine_info.lora_new_channel); getRtcTime(&Machine_info); // 获取当前时间 // 更新当前时间 Machine_info.current_button.button_info = button_info; Machine_info.current_button.Year = Machine_info.year; Machine_info.current_button.Month = Machine_info.month; Machine_info.current_button.Day = Machine_info.day; Machine_info.current_button.Hour = Machine_info.hour; Machine_info.current_button.Minute = Machine_info.min; Machine_info.current_button.Second = Machine_info.sec; long long current_Duration_time = calculate_minutes_difference( Machine_info.last_button.Year, Machine_info.last_button.Month, Machine_info.last_button.Day, Machine_info.last_button.Hour, Machine_info.last_button.Minute, Machine_info.last_button.Second, Machine_info.current_button.Year, Machine_info.current_button.Month, Machine_info.current_button.Day, Machine_info.current_button.Hour, Machine_info.current_button.Minute, Machine_info.current_button.Second); Machine_info.Duration_time = current_Duration_time; // 持续时长 printf("Machine_info.Duration_time = %ld\r\n", Machine_info.Duration_time); reset_btn_last_time(); #if 0 printf("list before\r\n"); printList(Send_list); if(Machine_info.Duration_time == 0) { deleteNode_head(Send_list); } printf("list after\r\n"); printList(Send_list); #endif set_status_heights(); Machine_info.Duration_time = 0; // 更新上次的状态 update_last_button_info(Machine_info.last_button.button_info); } else { printf("not add data to list\r\n"); } Machine_info.last_button.button_info = Machine_info.current_button.button_info; // Machine_info.left_state = button_info; Machine_info.left_state = Machine_info.current_button.button_info; #if 1 set_screen_dis_info_and_send_queue(true, true, false, false, 100); #endif beep_blink(30, 1); // printList(Send_list); // printList(list_head); } else // 和上个按键重复,唤醒原因为ulp唤醒,不进入休眠 { printf("repeat ,goto sleep !\r\n"); // sleep_timer_start(100); // 开始进入倒计时休眠 set_screen_dis_info_and_send_queue(false, false, false, true, 1000); } } else // 右屏幕按键触发 { if (button_info == POWER_ON_PRESS_VALUE) // power 开机时短按 { beep_blink(30, 1); if ((Machine_info.power_status == 1) && (Machine_info.paired == 1)) { // 判断当前开机 是否配对 继续执行时间片操作 // sleep_timer_start(100); // 开始进入倒计时休眠 set_screen_dis_info_and_send_queue(false, false, false, true, 1000); } } // if (button_info == POWER_OFF_PRESS_VALUE) // power 关机时短按 // { // sleep_timer_start(100); // 开始进入倒计时休眠 // } if (button_info == POWER_ON_INTO_STATUS_CHANGE_VALUE) // power 长按触发 { extern bool is_sleep; is_sleep = false; // 强制不休眠 beep_blink(1000, 1); if (Machine_info.power_status == 1) // 开机状态 { // Machine_info.power_status = 0; // screen_dis_info.is_change_power = true; xQueueReset(screen_queue); set_screen_dis_info_and_send_queue(false, true, false, false, 100); set_screen_dis_info_and_send_queue(true, false, true, false, 1000); // 关机 printf("poweron->poweroff\r\n"); } else if (Machine_info.power_status == 0) { printf("power on\r\n"); Machine_info.power_status = 1; lora_set_power_level(1); font_exit_sleep(); gpio_hold_dis(LORA_TXD_PIN); gpio_hold_dis(LORA_RXD_PIN); gpio_hold_dis(PIN_L_CS); gpio_hold_dis(PIN_R_CS); // 恢复串口i功能 uart_sleep_out_config(); set_screen_dis_info_and_send_queue(false, true, false, false, 100); set_screen_dis_info_and_send_queue(true, false, false, false, 100); } } if (button_info == POWER_ON_INTO_DIS_RIGHT) { xQueueReset(screen_queue); Machine_info.left_current_Quick_refresh_time = 5; set_screen_dis_info_and_send_queue(false, true, false, false, 100); set_screen_dis_info_and_send_queue(true, false, false, false, 100); } if (button_info == POWER_ON_INTO_OTA_VALUE) // 进入OTA模式 { beep_blink(50, 3); printf("into ota mode\r\n"); #include "iot_button.h" iot_button_stop(); esp_ble_ota(); } if (button_info == POWER_ON_INTO_RESET_VALUE) // 进入配网模式 { beep_blink(2000, 1); printf("into reset mode\r\n"); font_exit_sleep(); lora_set_power_level(1); uart_sleep_out_config(); #include "user_sleep.h" // #include "esp_sleep.h" extern void sleep_timer_stop(); extern void Already_send_timer_stop(); sleep_timer_stop(); Already_send_timer_stop(); // //修改信道前修改设备ID 及 设备ID // dymatic_change_device_id(0x00000001); // dymatic_change_dst_device_id(0xFFFFFFFF); // //切换信道 // dymatic_change_chanel(Machine_info.lora_factory_channel); //切换信道 // // spiffs_read(&Machine_info); vTaskDelay(300 / portTICK_PERIOD_MS); reset_default(true, 1); reset_lora(LORA_CHANENL); vTaskDelay(300 / portTICK_PERIOD_MS); } } } } } static void business_logic_task(void *arg) { // YC_DATA_T tmp; int len = 0; bool is_refresh = false; for (;;) { if (xQueueReceive(yc_data_queue, &len, (TickType_t)portMAX_DELAY)) { #if 1 is_refresh = subcontract(&yc_data); if (is_refresh) { screen_display(); } else { printf("not display fresh\r\n"); } #endif free(yc_data.data); // 释放内存 yc_data.data = NULL; yc_data.len = 0; yc_data.index = 0; } } } static void unpack_task(void *arg) { LORA_DATA_T tmp_data; extern esp_timer_handle_t lora_timer; for (;;) { if (xQueueReceive(lora_data_queue, &tmp_data, (TickType_t)portMAX_DELAY)) { if (!esp_timer_is_active(lora_timer)) { lora_timer_start(); } else { lora_timer_restart(); } yc_data.len += tmp_data.data_len; memcpy(yc_data.data + yc_data.index, tmp_data.data_buf, tmp_data.data_len); yc_data.index += tmp_data.data_len; } } } static void lora_task(void *arg) { lora_event_task(arg); } // /********************************************************************************* // * function : Sendlist_task_callback_handler // * Description : 发送处理链表函数 // * Input : // * Output : // * Author : 祁鑫 Data : 2023 9.12 // **********************************************************************************/ // void Sendlist_task_callback_handler() // { // int length = 0; // uint8_t* result = (uint8_t*) malloc(buffer_size+1); // TickType_t xLastWakeTime; // #if 0 // const TickType_t xFrequency = 400/10; // 定时通知的间隔 // #else // const TickType_t xFrequency = 500/10; // 定时通知的间隔 // #endif // // 初始化xLastWakeTime // xLastWakeTime = xTaskGetTickCount(); // int receive_times = 0; // int user_size = 0; // int result_length = 0; // //int result_length = 0; // static int result_index = 0; // int result_data_len = 0; // while (1) { // #if 0 // //定时通知数据处理任务有新数据可用 // vTaskDelayUntil(&xLastWakeTime, xFrequency); // #endif // if(xQueueReceive(Send_Data_queue, &length, portMAX_DELAY) == pdPASS) // { // //int len = countNodes(Send_list); /* returns the number of nodes in the list */ // Node *list = Send_list; //发送数据链表 // int len = countNodes(Send_list); /* returns the number of nodes in the list */ // if(len!=0) // { // printf("current wait send num data=%d\r\n",len); // #if 1 // //int len = countNodes(list); /* returns the number of nodes in the list */ // while(len) // { // //int busy = get_lora_busy_pin(); // //printf("busy = %d\r\n",busy); // printf("send times\r\n"); // //if() // lora_send_data((char *)list->data,list->len); // list=list->next; // len--; // } // //Send_list = deleteList(Send_list); // free(list); // #endif // } // #if 0 // for (int i = 0; i < len; i++) // { // printf("%02x",result[i]); // } // #endif // } // } // } /********************************************************************************* * function : uart_task_callback_handler * Description : 串口0函数 * Input : * Output : * Author : 祁鑫 Data : 2023 9.12 **********************************************************************************/ void uart_task_callback_handler() { // #include "driver/uart.h" // uint8_t dtmp[200]= {0}; // while (1) // { // printf("uart 0 rev = "); // int len = uart_read_bytes(UART_NUM_0, dtmp, 1024,200/portTICK_PERIOD_MS); // if(len) // { // for(int i = 0;i=0) #endif if(user_size>0) { #if 0 for (int i = 0; i < len; i++) { printf("%02x",result[i]); } #endif printf("times comming length=%d\r\n",user_size); if(user_size == 36) { y_ringbuf_read_clear(lora_ringbuf, result, user_size); //读取并清除数据 } #if 1 int len = y_ringbuf_read_clear(lora_ringbuf, result, user_size); //读取并清除数据 yc_data.len = user_size; yc_data.data = malloc(sizeof(uint8_t)*user_size);//分配内存 memcpy(yc_data.data,result,user_size); //lora_send_queue_callback(result,len); //发送消息处理函数 if(xQueueSend(yc_data_queue,&len,0) != true) { ESP_LOGE(LOG_TAG,"yc_data_queue send is fail"); } #endif #if USER_OTA if((user_size>1024)||(user_size == 0) || (((user_size<1024))&&(is_ota ==true)) ) if(xQueueSend(ota_queue,&user_size,0) != true) { ESP_LOGE(LOG_TAG,"ota_queue send is fail"); } #endif } } #else int length = 0; uint8_t *result = (uint8_t *)malloc(buffer_size + 1); int user_size = 0; while (1) { if (xQueueReceive(lora_dealhandle, &length, portMAX_DELAY) == pdPASS) { if (rssi != 0) { Machine_info.rssi = rssi; } // printf("deal data\r\n"); user_size = y_ringbuf_get_used_size(lora_ringbuf); if (user_size > 0) { ESP_LOGI(LOG_TAG, "-->lora len = %d\r\n", user_size); #if 0 if(user_size == 36) { y_ringbuf_read_clear(lora_ringbuf, result, user_size); //读取并清除数据 #if 1 for (int i = 0; i < user_size; i++) { printf("%02x",result[i]); } #endif }else #endif { #if 1 int len = y_ringbuf_read_clear(lora_ringbuf, result, user_size); // 读取并清除数据 #if 0 for (int i = 0; i < user_size; i++) { printf("%02x",result[i]); } printf("\r\n"); #endif ESP_LOG_BUFFER_HEX("from gateway lora", result, user_size); yc_data.len = user_size; yc_data.data = malloc(sizeof(uint8_t) * user_size); // 分配内存 memcpy(yc_data.data, result, user_size); // lora_send_queue_callback(result,len); //发送消息处理函数 if (xQueueSend(yc_data_queue, &len, (TickType_t)portMAX_DELAY) != true) { ESP_LOGE(LOG_TAG, "yc_data_queue send is fail"); } #endif } } } } #endif }