#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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 "iot_button.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)
            {
                ESP_LOGW(LOG_TAG,"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
                printf("esp_deep_sleep_start\r\n");
                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(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(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();
            is_epd_ok_cplt = false;
            if (screen_rev_info.is_left) // 刷左屏
            {
                if (screen_rev_info.is_change_power)
                {
                    ESP_LOGE(LOG_TAG, "power_status:%s", Machine_info.power_status ? "now[poweron],after[poweroff]" : "now[poweroff],after[poweron]");
                    Machine_info.power_status = !Machine_info.power_status; // 关机
                }
                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);
                }
            }
            is_epd_ok_cplt = true;
        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_LOGW(LOG_TAG, "%dms sleep  %s", screen_rev_info.sleep_ms, screen_rev_info.is_left ? "left" : "right");
                sleep_timer_start(screen_rev_info.sleep_ms); // 进入睡眠
            }

            if (Machine_info.power_status == 0) // 展示说明书都是先左后右，等右屏刷完再休眠
            {
                ESP_LOGW(LOG_TAG, "now is power off");
                sleep_timer_start(1000); // 进入睡眠
            }
            // ESP_LOGW(LOG_TAG, "screen task over");
        }
    }
}

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);
                    }
                }
                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();

                        // 更新上次的状态
                        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(true, false, false, true, 100);
                }
            }
            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) // 开机状态
                    {
                        printf("poweron->poweroff\r\n");
                        lora_set_power_level(0); // 关机关闭lora防止lora消息刷屏
                        // Machine_info.power_status = 0;
                        // screen_dis_info.is_change_power = true;
                        xQueueReset(screen_queue);
                        set_screen_dis_info_and_send_queue(false, true, true, false, 5000); // 关机
                        set_screen_dis_info_and_send_queue(true, false, false, false, 5000);
                    }
                    else if (Machine_info.power_status == 0) // 关机后还未进入休眠直接长按开机
                    {
                        printf("button power on\r\n");
                        Machine_info.power_status = 1;

                        gpio_hold_dis(LORA_TXD_PIN);
                        gpio_hold_dis(LORA_RXD_PIN);

                        gpio_hold_dis(PIN_L_CS);
                        gpio_hold_dis(PIN_R_CS);

                        set_screen_dis_info_and_send_queue(false, true, false, false, 100);
                        set_screen_dis_info_and_send_queue(true, false, false, false, 100);

                        lora_set_power_level(1);
                        // 恢复串口i功能
                        uart_sleep_out_config();
                        font_exit_sleep();
                    }
                }

                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");

                    iot_button_stop();
                    esp_ble_ota();
                }

                if (button_info == POWER_ON_INTO_RESET_VALUE) // 进入配网模式
                {
                    is_change_chanel_ok = false;

                    printf("into reset mode\r\n");

                    font_exit_sleep();
                    lora_set_power_level(1);
                    uart_sleep_out_config();
                    beep_blink(2000, 1);
                    extern void sleep_timer_stop();
                    extern void Already_send_timer_stop();

                    sleep_timer_stop();
                    Already_send_timer_stop();

                    vTaskDelay(300 / portTICK_PERIOD_MS);
                    reset_default(true, 1);
                    reset_lora(LORA_CHANENL);
                }
            }
        }
    }
}

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<len;i++)
    //         printf("%02X",dtmp[i]);
    //         printf("\r\n");

    //         }

    //         printf("\r\n");

    //         vTaskDelay(1000 / portTICK_PERIOD_MS);
    //     }
}

/*********************************************************************************
 * function   :   read_deal_data_callback_handler
 * Description :  定时处理函数
 * Input       :
 * Output      :
 * Author      :  祁鑫                  Data : 2023 9.12
 **********************************************************************************/
void read_deal_data_callback_handler()
{

#if 0
  int length = 0;


 	 uint8_t* result = (uint8_t*) malloc(buffer_size+1);

 	TickType_t xLastWakeTime;
#if 1
    const TickType_t xFrequency = 100/10; // 定时通知的间隔
#else
    const TickType_t xFrequency = 500; // 定时通知的间隔
#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;

#include "y_ringbuf.h"
    extern struct RINGBUF_st;
    extern RINGBUF_st *lora_ringbuf;


  while (1) {

	 // 定时通知数据处理任务有新数据可用
        vTaskDelayUntil(&xLastWakeTime, xFrequency);
		user_size = y_ringbuf_get_used_size(lora_ringbuf);
#if USER_OTA
        if(user_size>=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)
        {
            // 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
}
