#include "GUI_tjc_hmi.h" #include #include #include #include #include #include "proto_modbus_lib.h" #include "bsp_w25q.h" // 添加Flash操作 #include "bsp_W5500.h" #include "bsp_uart.h" #include "bsp_DS1302.h" #include "bsp_buzzer.h" #include "app_leakage.h" #include "app_com.h" /*串口发送缓冲区*/ #define HMI_TX_BUFFER_NUM (2048) /*字符发送拼接 缓冲区*/ #define GUI_TJC_HMI_TEXT_BUFFER_NUM (256) /*帧头*/ #define HMI_PROTO_FRAME_HEADER1 (0xAA) #define HMI_PROTO_FRAME_HEADER2 (0x55) /*操作*/ #define HMI_PROTO_CMD_GET (0x03) /*获取数据数据*/ #define HMI_PROTO_CMD_SET (0x10) /*设置信息*/ /*界面*/ #define HMI_PROTO_GUI_MAIN (0x10)/*主界面 */ #define HMI_PROTO_GUI_CURR_ALARM (0x11)/*实时报警界面 */ #define HMI_PROTO_GUI_DETAIL_MAIN (0x12)/*主界面_详细信息 */ #define HMI_PROTO_GUI_LOGIN (0x13)/*登录界面 */ #define HMI_PROTO_GUI_HISTORY_ALARM (0x14)/*历史报警界面 */ #define HMI_PROTO_GUI_TCP_CONFIG (0x15)/*网络配置界面 */ #define HMI_PROTO_GUI_DEVICE_CONFIG (0x16)/*设备配置界面 */ #define HMI_PROTO_GUI_HELP (0x17)/*帮助界面 */ #define HMI_PROTO_GUI_TIME (0x18)/*时间设置界面*/ #define HMI_PROTO_ASCII_RX_DELINITER (0xAA)/*接收分隔符*/ #define HMI_PROTO_ASCII_TX_DELINITER (0xFF)/*发送分隔符*/ #define HMI_PROTO_ASCII_TX_DELINITER_NUM (3)/*发送分隔符数量*/ #define W25Q32_PASSWORD_ADDR (W25Q32_USER_DATA_ADDR)/*密码存储地址*/ static void gui_tjc_hmi_init(void); static void gui_tjc_hmi_communication_data_analysis(u8 *p_data, u16 len, void *rx_uart); /*串口发送缓冲区*/ static u8 hmi_tx_buffer[HMI_TX_BUFFER_NUM]; /*字符发送拼接 缓冲区*/ static char gui_tjc_hmi_text_buffer[GUI_TJC_HMI_TEXT_BUFFER_NUM]; /*字符名称 端口号*/ static char *hmi_proto_string_com[] = { "COM1", "COM2", "COM3", "COM4" }; /*字符名称 波特率*/ static char *hmi_proto_string_baudrate[] = { "2400", "4800", "9600", "115200", }; static bsp_uart_t * p_rx_uart = NULL; gui_tjc_hmi_t tjc_hmi = { .init = gui_tjc_hmi_init, }; gui_tjc_hmi_t *p_tjc_hmi = &tjc_hmi; static void gui_tjc_hmi_class_update(void) { leakage.class_update(); app_com.class_update(); } /*屏幕协议初始化*/ static void gui_tjc_hmi_init(void) { com_uart1.rx_data_analysis = gui_tjc_hmi_communication_data_analysis; } /*发送接口*/ static void gui_tjc_hmi_data_send(u8 *p_data,u16 len) { if(p_rx_uart != NULL) { p_rx_uart->send(p_rx_uart,p_data,len); } } static void gui_tjc_hmi_read_password_from_w25q(void) { /*直接读取4字节密码*/ w25q32.read(W25Q32_PASSWORD_ADDR, p_tjc_hmi->password, 4); /*检查数据有效性,如果全部为0xFF,说明是首次使用,清空密码*/ if(p_tjc_hmi->password[0] == 0xFF && p_tjc_hmi->password[1] == 0xFF && p_tjc_hmi->password[2] == 0xFF && p_tjc_hmi->password[3] == 0xFF) { memset(p_tjc_hmi->password, 0, 4); } } /*将密码保存到W25Q32*/ static void gui_tjc_hmi_save_password_to_w25q(void) { uint32_t erase_addr = W25Q32_PASSWORD_ADDR & ~(W25Q32_SECTOR_SIZE - 1); w25q32_sector_erase(erase_addr); /*将4字节密码写入W25Q32*/ w25q32.write(W25Q32_PASSWORD_ADDR, p_tjc_hmi->password, 4); } /* 将设备信息从app_leakage保存到W25Q32 */ static void gui_tjc_hmi_save_device_info_to_w25q(void) { /* 创建一个临时缓冲区 */ app_leakage_sub_device_flash_data_t temp_buffer[APP_LEAKAGE_SUB_DEVICE_NUM]; /* 从app_leakage结构体复制到临时缓冲区 */ for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { temp_buffer[i] = leakage.sub_device_data[i].flash_data; } /* 添加Flash擦除操作 - 必须擦除后才能写入 */ uint32_t erase_addr = W25Q32_DEVICE_INFO_ADDR; /* 确保地址是4K对齐(W25Q32_SECTOR_SIZE = 4096) */ erase_addr &= ~(W25Q32_SECTOR_SIZE - 1); /* 擦除整个扇区 */ w25q32_sector_erase(erase_addr); /* 一次性写入所有设备信息 */ w25q32.write(W25Q32_DEVICE_INFO_ADDR, (uint8_t*)temp_buffer, DEVICE_INFO_STORAGE_SIZE); } /*解析网络函数*/ static void parse_ip_string(u8 *str, u8 len, u8 *ip) { u8 i = 0, part = 0, val = 0; while (i < len) { if (str[i] == '.') { ip[part++] = val; val = 0; } else if (str[i] >= '0' && str[i] <= '9') { val = val * 10 + (str[i] - '0'); } i++; } ip[part] = val; // 最后一个部分 } /*设置对应的控件 x:第几行 y:第几个 buffer:写入的buffer format:格式化输入 ...:不定长 */ static u16 gui_tjc_hmi_tx_text_display(u16 x,u16 y,char *buffer,const char *format,...) { u16 i,len; s16 state; va_list arg; /*清空缓冲区*/ memset(gui_tjc_hmi_text_buffer,0,sizeof(gui_tjc_hmi_text_buffer)); va_start(arg,format); /*格式化转成字符串*/ state = vsnprintf(gui_tjc_hmi_text_buffer,GUI_TJC_HMI_TEXT_BUFFER_NUM,format,arg); if(-1 == state || state > GUI_TJC_HMI_TEXT_BUFFER_NUM) { va_end(arg); printf("Length REEOR"); return 0; } /*拼接字符串*/ sprintf(buffer,"t%d_%d.txt=\"%s\"",x,y,gui_tjc_hmi_text_buffer); len = strlen(buffer); for(i=0;i 0) { page_num++; } char time[20]; sprintf(time,"20%d-%02d-%02d %02d:%02d:%02d", DS1302.Time.Year, DS1302.Time.Month, DS1302.Time.Day, DS1302.Time.Hour, DS1302.Time.Minute, DS1302.Time.Second); len += gui_tjc_hmi_tx_text_display(0,0,(char *)&hmi_tx_buffer[len],"%s",time); /*IP地址*/ len += gui_tjc_hmi_tx_text_display(0,1,(char *)&hmi_tx_buffer[len], "%d.%d.%d.%d", W5500.IP_Addr[0], W5500.IP_Addr[1], W5500.IP_Addr[2], W5500.IP_Addr[3]); /*蜂鸣器状态*/ u8 buzzer_state = (buzzer.p_flash_data->sw == USR_ENABLE) ? 11 : 13; /*构造 "sw0.val=x" 指令(x 为 0 或 1)*/ len += sprintf((char*)&hmi_tx_buffer[len], "p4.pic=%d", buzzer_state); for (u8 i = 0; i < 3; i++) { hmi_tx_buffer[len + i] = 0xFF; } len += 3; if(HMI_PROTO_CMD_GET == cmd)/*获取数据*/ { switch(opa) { case 0x01:/*读取区域信息*/ { if (leakage.region_num == 0) { for (j = 0; j < MAIN_PAGE_SUB_DEVICE_NUM; j++) { for (y = 0; y < 5; y++) { len += gui_tjc_hmi_tx_text_display(j+1, y+1, (char *)&hmi_tx_buffer[len], ""); } } break; } if(p_tjc_hmi->page.main_index == page_num - 1 && remain_region_num >0)/*显示剩余区域*/ { for(j=0;jpage.main_index * MAIN_PAGE_SUB_DEVICE_NUM + j; x = j; /*名称*/ y = 0; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.region_data[index].name); /*区域内设备总数量*/ y = 1; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].sub_device_num); /*漏液数量*/ y = 2; if(leakage.region_data[index].leakage_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].leakage_num); } /*断带*/ y = 3; if(leakage.region_data[index].open_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].open_num); } /*通讯*/ y = 4; if(leakage.region_data[index].time_out_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].time_out_num); } } // 清除多余列的所有行(设置为空字符串) for(j = remain_region_num; j < MAIN_PAGE_SUB_DEVICE_NUM; j++) { for(y = 0; y < 5; y++) // 共有5行数据 { len += gui_tjc_hmi_tx_text_display(j+1, y+1, (char *)&hmi_tx_buffer[len], ""); } } } else { for(j=0;jpage.main_index*MAIN_PAGE_SUB_DEVICE_NUM + j; x = j; /*名称*/ y = 0; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.region_data[index].name); /*区域内设备总数量*/ y = 1; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].sub_device_num); /*漏液数量*/ y = 2; if(leakage.region_data[index].leakage_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].leakage_num); } /*断带*/ y = 3; if(leakage.region_data[index].open_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].open_num); } /*通讯*/ y = 4; if(leakage.region_data[index].time_out_num == 0) { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s","Normal"); }else { len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.region_data[index].time_out_num); } } } }break; case 0x03:/*翻页*/ { if(0x01 == p_data[5]) { if(page_num - 1 <= p_tjc_hmi->page.main_index) { p_tjc_hmi->page.main_index = 0; } else { p_tjc_hmi->page.main_index++; } } else { if(0 == p_tjc_hmi->page.main_index) { p_tjc_hmi->page.main_index = page_num - 1; } else { p_tjc_hmi->page.main_index--; } } } default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if(HMI_PROTO_CMD_SET == cmd)/*设置*/ { switch(opa) { case 0x01:/*蜂鸣器开关*/ { if(0x01 == p_data[0]) { /*01打开蜂鸣器*/ buzzer.set.enable(); } else { /*00关闭蜂鸣器*/ buzzer.set.disable(); } } default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } } /*实时报警响应*/ static void gui_tjc_hmi_curr_alarm_send(u8 cmd,u8 opa,u8 *p_data) { /*每页显示的报警设备数量*/ #define REAL_ALARM_PAGE_NUM (4) u16 len = 0,i,j,x,y,device_index,ch,index; u8 page_num,remain_alrm_device_num,display_count; u8 alarm_device_count; u8 alarm_device_index[APP_LEAKAGE_SUB_DEVICE_NUM]; memset(hmi_tx_buffer,0,sizeof(hmi_tx_buffer)); /*计算报警设备数量*/ alarm_device_count = 0; for(i = 0;i 0) { page_num++; } if(HMI_PROTO_CMD_GET == cmd)/*获取数据*/ { switch(opa) { case 0x01:/*获取实时报警信息*/ { if(p_tjc_hmi->page.real_alarm_index == page_num - 1 && remain_alrm_device_num > 0) { for(j=0;jpage.real_alarm_index * REAL_ALARM_PAGE_NUM + j; device_index = alarm_device_index[index]; x = j; /*区域名称*/ y = 0; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.sub_device_data[device_index].flash_data.region_name); /*设备ID*/ y = 1; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.sub_device_data[device_index].flash_data.modbus_id); /*设备名称*/ y = 2; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.sub_device_data[device_index].flash_data.device_name); /*通讯状态*/ y =3; u16 comm_state = 0; for(ch=0;chpage.real_alarm_index * REAL_ALARM_PAGE_NUM + j; device_index = alarm_device_index[index]; x = j; /*区域名称*/ y = 0; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.sub_device_data[device_index].flash_data.region_name); /*设备ID*/ y = 1; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%d",leakage.sub_device_data[device_index].flash_data.modbus_id); /*设备名称*/ y = 2; len += gui_tjc_hmi_tx_text_display(x+1,y+1,(char *)&hmi_tx_buffer[len],"%s",leakage.sub_device_data[device_index].flash_data.device_name); /*通讯状态*/ y =3; u16 comm_state = 0; for(ch=0;chpage.real_alarm_index) { p_tjc_hmi->page.real_alarm_index = 0; } else { p_tjc_hmi->page.real_alarm_index++; } } else { if(0 == p_tjc_hmi->page.real_alarm_index) { p_tjc_hmi->page.real_alarm_index = page_num - 1; } else { p_tjc_hmi->page.real_alarm_index--; } } } default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if(HMI_PROTO_CMD_SET == cmd)/*设置*/ { switch(opa) { case 0x01: { }break; case 0x02: { }break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } } /*主界面详情*/ static void gui_tjc_hmi_detail_main_send(u8 cmd, u8 opa, u8 *p_data) { #define DETAIL_MAIN_NUM (4) /* 每页显示4个设备 */ u16 len = 0, i, sub_device_index, ch, x, y, index; u8 page_num, remain_device_num, display_count; u8 region_idx; /* 区域索引 */ app_leakage_region_data_class_t *region_data; memset(hmi_tx_buffer, 0, sizeof(hmi_tx_buffer)); // /* 计算详情页面数量:每页显示4个设备 */ // page_num = region_data->sub_device_num / DETAIL_MAIN_NUM; // remain_device_num = region_data->sub_device_num % DETAIL_MAIN_NUM; // if (remain_device_num > 0) // { // page_num++; // } if (HMI_PROTO_CMD_GET == cmd) /* 获取数据 */ { switch (opa) { case 0x01: /* 获取设备详情信息 */ { u8 relative_region_idx = p_data[0]; if (relative_region_idx < 1 || relative_region_idx > 4) return; /* 计算全局区域索引 */ region_idx = p_tjc_hmi->page.main_index * 4 + (relative_region_idx - 1); if (region_idx >= leakage.region_num) return; /* 切换区域时重置详情页码 */ if (region_idx != p_tjc_hmi->page.deliniter_main_index) p_tjc_hmi->page.detail_main_index = 0; p_tjc_hmi->page.deliniter_main_index = region_idx; region_data = &leakage.region_data[region_idx]; /* 计算页面参数 */ page_num = region_data->sub_device_num / DETAIL_MAIN_NUM; remain_device_num = region_data->sub_device_num % DETAIL_MAIN_NUM; if (remain_device_num > 0) page_num++; if (page_num == 0) page_num = 1; u8 start_index = p_tjc_hmi->page.detail_main_index * DETAIL_MAIN_NUM; display_count = (p_tjc_hmi->page.detail_main_index == page_num - 1 && remain_device_num > 0) ? remain_device_num : DETAIL_MAIN_NUM; for (i = 0; i < display_count; i++) { index = start_index + i; if (index >= region_data->sub_device_num) break; sub_device_index = region_data->sub_device_index[index]; x = i; /* 设备ID: t(x+1)_1 */ y = 0; len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "%d", leakage.sub_device_data[sub_device_index].flash_data.modbus_id); /* 设备名称: t(x+1)_2 */ y = 1; len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "%s", leakage.sub_device_data[sub_device_index].flash_data.device_name); /* 通讯状态: t(x+1)_3 */ y = 2; u8 comm_state = 0; for (ch = 0; ch < APP_LEAKAGE_SUB_DEVICE_CH_NUM; ch++) { if (leakage.sub_device_data[sub_device_index].ch_data[ch].state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT) { comm_state = 1; break; } } if(leakage.sub_device_data[sub_device_index].flash_data.shield == UNBLOCKED) { if (comm_state) { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "超时"); } else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } }else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } /* 通道1-4状态 */ for (ch = 0; ch < APP_LEAKAGE_SUB_DEVICE_CH_NUM; ch++) { u16 ch_state = leakage.sub_device_data[sub_device_index].ch_data[ch].state; u16 ch_distance = leakage.sub_device_data[sub_device_index].ch_data[ch].distance; /* 漏液状态 */ y = 3 + (ch * 3); if(leakage.sub_device_data[sub_device_index].flash_data.shield == UNBLOCKED) { if (ch_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE) { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "漏液"); } else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } }else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } /* 断带状态 */ y = 4 + (ch * 3); if(leakage.sub_device_data[sub_device_index].flash_data.shield == UNBLOCKED) { if (ch_state & APP_LEAKAGE_SUB_DEVICE_STATE_OPEN) { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "断带"); } else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } }else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "正常"); } /* 漏液位置 */ y = 5 + (ch * 3); if(leakage.sub_device_data[sub_device_index].flash_data.shield == UNBLOCKED) { if (ch_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE) { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "%d", ch_distance); } else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "0"); } }else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "0"); } } /* 屏蔽状态显示: t(x+1)_16 */ y = 15; // 第16列对应y=15 if (leakage.sub_device_data[sub_device_index].flash_data.shield == BLOCKED) { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "禁用中"); } else { len += gui_tjc_hmi_tx_text_display(x+1, y+1, (char *)&hmi_tx_buffer[len], "启用中"); } } /*清空未使用的*/ for (; i < DETAIL_MAIN_NUM; i++) { x = i; len += gui_tjc_hmi_tx_text_display(x+1, 1, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(x+1, 2, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(x+1, 3, (char *)&hmi_tx_buffer[len], ""); for (ch = 0; ch < APP_LEAKAGE_SUB_DEVICE_CH_NUM; ch++) { len += gui_tjc_hmi_tx_text_display(x+1, 4 + (ch*3), (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(x+1, 5 + (ch*3), (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(x+1, 6 + (ch*3), (char *)&hmi_tx_buffer[len], ""); } len += gui_tjc_hmi_tx_text_display(x+1, 16, (char *)&hmi_tx_buffer[len], ""); } } break; case 0x03: /* 翻页 */ { region_idx = p_tjc_hmi->page.deliniter_main_index; if (region_idx >= leakage.region_num) return; region_data = &leakage.region_data[region_idx]; /*重新计算页数*/ page_num = region_data->sub_device_num / DETAIL_MAIN_NUM; remain_device_num = region_data->sub_device_num % DETAIL_MAIN_NUM; if (remain_device_num > 0) page_num++; if (page_num == 0) page_num = 1; if(0x01 == p_data[0]) /* 下一页 */ { if(page_num - 1 <= p_tjc_hmi->page.detail_main_index) { p_tjc_hmi->page.detail_main_index = 0; } else { p_tjc_hmi->page.detail_main_index++; } } else /* 上一页 */ { if(0 == p_tjc_hmi->page.detail_main_index) { p_tjc_hmi->page.detail_main_index = page_num - 1; } else { p_tjc_hmi->page.detail_main_index--; } } return; } break; default: return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if (HMI_PROTO_CMD_SET == cmd) /* 设置命令 */ { switch (opa) { case 0x01: /* */ { u8 len_id = 0; u8 device_id = 0; /* 解析设备ID:从p_data[0]开始,直到遇到分隔符 */ while (p_data[len_id] != HMI_PROTO_ASCII_RX_DELINITER) { if (p_data[len_id] < '0' || p_data[len_id] > '9') { return; /* 非法字符 */ } len_id++; if (len_id > 3) { /* ID最多3位数字(0-255) */ return; } } if (len_id == 0) { return; /* ID不能为空 */ } /* 将ASCII数字串转换为数值 */ char id_str[4] = {0}; /* 最多3位数字加'\0' */ memcpy(id_str, p_data, len_id); id_str[len_id] = '\0'; int temp_id = atoi(id_str); if (temp_id < 0 || temp_id > 255) { return; /* ID超出范围 */ } device_id = (u8)temp_id; /* 检查操作码及其后的分隔符 */ u8 op_index = len_id + 1; /* 操作码位置 */ u8 delim_index = len_id + 2; /* 操作码后的分隔符位置 */ if (p_data[delim_index] != HMI_PROTO_ASCII_RX_DELINITER) { return; } u8 operation = p_data[op_index]; /* 操作码直接作为数值 */ /* 遍历所有使能的设备,查找匹配的modbus_id */ u8 found = 0; for (u8 i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { if (leakage.sub_device_data[i].flash_data.state == ENABLE && leakage.sub_device_data[i].flash_data.modbus_id == device_id) { if (operation == 0x01) { leakage.sub_device_data[i].flash_data.shield = BLOCKED; /* 屏蔽 */ } else if (operation == 0x02) { leakage.sub_device_data[i].flash_data.shield = UNBLOCKED; /* 恢复 */ } else { return; } found = 1; break; } } if (found) { /*将修改后的设备信息保存到 Flash*/ gui_tjc_hmi_save_device_info_to_w25q(); } return; } break; default: return; } } } /*登录界面*/ static void gui_tjc_hmi_login_send(u8 cmd,u8 opa,u8 *p_data) { u16 len = 0,i; if(HMI_PROTO_CMD_GET == cmd) /* 获取数据 */ { switch(opa) { case 0x01: /* 读取flash中存储的密码 */ { gui_tjc_hmi_read_password_from_w25q(); memset(hmi_tx_buffer, 0, sizeof(hmi_tx_buffer)); /* 将密码数值以连续数字形式发送到控件 t22_1 */ len = gui_tjc_hmi_tx_text_display(22, 1, (char *)hmi_tx_buffer, "%d%d%d%d", p_tjc_hmi->password[0], p_tjc_hmi->password[1], p_tjc_hmi->password[2], p_tjc_hmi->password[3]); gui_tjc_hmi_data_send(hmi_tx_buffer, len); return; /* 直接返回,避免外层重复发送 */ } break; case 0x02: /* 无操作 */ default: return; } } else if(HMI_PROTO_CMD_SET == cmd) /* 设置数据 */ { switch(opa) { case 0x01: /* 将密码存入flash */ { /* 将ASCII码转换为数值('0'~'9') */ for(i = 0; i < 4; i++) { if(p_data[i] >= '0' && p_data[i] <= '9') { p_tjc_hmi->password[i] = p_data[i] - '0'; } else { p_tjc_hmi->password[i] = 0; /* 非法字符时清零 */ } } /* 保存到W25Q32 */ gui_tjc_hmi_save_password_to_w25q(); /* 设置命令无需响应,直接返回 */ return; } break; case 0x02: /* 无操作 */ default: return; } } } /*历史报警界面*/ static void gui_tjc_hmi_history_alarm_send(u8 cmd,u8 opa,u8 *p_data) { #define HISTORY_ALARM_PER_PAGE (15) /* 每页15条历史报警数据 */ u16 len = 0, i, j; u8 page_num, remain_records, display_count; u32 total_records, start_index, record_index; app_leakage_history_alarm_t history_record; char time_str[20]; char alarm_type_str[20]; /* 获取总记录数 */ total_records = leakage.history_metadata.total_records; if(total_records == 0) { return; } /* 计算页面数量 */ page_num = total_records / HISTORY_ALARM_PER_PAGE; remain_records = total_records % HISTORY_ALARM_PER_PAGE; if(remain_records > 0) { page_num++; } if(HMI_PROTO_CMD_GET == cmd) /* 获取数据 */ { switch(opa) { case 0x01: /* 读取历史报警信息 */ { /* 获取当前页码对应的记录 */ u8 current_page = p_tjc_hmi->page.history_alarm_index; /* 计算起始记录索引(按时间倒序显示,最新的在前面) */ start_index = current_page * HISTORY_ALARM_PER_PAGE; /* 计算本页显示记录数 */ if(current_page == page_num - 1 && remain_records > 0) { display_count = remain_records; } else { display_count = HISTORY_ALARM_PER_PAGE; } /* 显示历史报警记录 */ for(i = 0; i < display_count; i++) { /* 计算记录索引(从最新的开始) */ if(total_records > start_index + i) { record_index = total_records - 1 - (start_index + i); } else { break; } /* 读取历史报警记录 */ if(history.read_history(record_index, &history_record)) { /* 区域名: t(i+1)_1 */ len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], "%s", history_record.region_name); /* 设备ID: t(i+1)_2 */ len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], "%d", history_record.device_id); /*通道信息:t(i+1)_3*/ len += gui_tjc_hmi_tx_text_display(i+1,3, (char *)&hmi_tx_buffer[len], "%d", history_record.channel); /* 报警类型: t(i+1)_4 */ alarm_type_str[0] = '\0'; if(history_record.alarm_type == APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE) strcat(alarm_type_str, "漏液"); else if(history_record.alarm_type == APP_LEAKAGE_SUB_DEVICE_STATE_OPEN) strcat(alarm_type_str, "断带"); else if(history_record.alarm_type == APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT) strcat(alarm_type_str, "通讯超时"); len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], "%s", alarm_type_str); /* 设备名称: t(i+1)_5 */ len += gui_tjc_hmi_tx_text_display(i+1, 5, (char *)&hmi_tx_buffer[len], "%s", history_record.device_name); /* 漏液距离: t(i+1)_6 (如果是漏液报警才显示) */ if(history_record.alarm_type == APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE) { len += gui_tjc_hmi_tx_text_display(i+1, 6, (char *)&hmi_tx_buffer[len], "%d", history_record.leak_distance); } else { len += gui_tjc_hmi_tx_text_display(i+1, 6, (char *)&hmi_tx_buffer[len], "0"); } /* 开始时间: t(i+1)_7 */ uint16_t year = (history_record.start_time[0] << 8) | history_record.start_time[1]; sprintf(time_str, "%04d-%02d-%02d %02d:%02d:%02d", year, history_record.start_time[2], history_record.start_time[3], history_record.start_time[4], history_record.start_time[5], history_record.start_time[6]); len += gui_tjc_hmi_tx_text_display(i+1, 7, (char *)&hmi_tx_buffer[len], "%s", time_str); } else { /* 读取失败,显示空 */ len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 5, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 6, (char *)&hmi_tx_buffer[len], ""); } } /* 如果本页不足15条记录,清空剩余行 */ for(; i < HISTORY_ALARM_PER_PAGE; i++) { len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 5, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 6, (char *)&hmi_tx_buffer[len], ""); } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer, len); } break; case 0x03: /* 翻页 */ { if(0x01 == p_data[0]) /* 下一页 */ { if(p_tjc_hmi->page.history_alarm_index >= page_num - 1) { p_tjc_hmi->page.history_alarm_index = 0; } else { p_tjc_hmi->page.history_alarm_index++; } } else /* 上一页 */ { if(p_tjc_hmi->page.history_alarm_index == 0) { p_tjc_hmi->page.history_alarm_index = page_num - 1; } else { p_tjc_hmi->page.history_alarm_index--; } } } break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if(HMI_PROTO_CMD_SET == cmd)/*设置*/ { switch(opa) { case 0x01:/*清空*/ { history.clean_history(); p_tjc_hmi->page.history_alarm_index = 0; // 重置页码 memset(hmi_tx_buffer, 0, sizeof(hmi_tx_buffer)); len = 0; // // 清空所有15行的7列数据 // for(i = 0; i < HISTORY_ALARM_PER_PAGE; i++) // { // len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], ""); // 区域名 // len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], ""); // 设备ID // len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], ""); // 通道 // len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], ""); // 报警类型 // len += gui_tjc_hmi_tx_text_display(i+1, 5, (char *)&hmi_tx_buffer[len], ""); // 设备名称 // len += gui_tjc_hmi_tx_text_display(i+1, 6, (char *)&hmi_tx_buffer[len], ""); // 漏液距离 // len += gui_tjc_hmi_tx_text_display(i+1, 7, (char *)&hmi_tx_buffer[len], ""); // 时间 // } gui_tjc_hmi_data_send(hmi_tx_buffer, len); }break; case 0x02:/*无*/ { }break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } } /*网络配置界面*/ static void gui_tjc_hmi_tcp_config_send(u8 cmd,u8 opa,u8 *p_data) { u16 len = 0,i; memset(hmi_tx_buffer,0,sizeof(hmi_tx_buffer)); if(HMI_PROTO_CMD_GET == cmd)/*获取数据*/ { switch(opa) { case 0x01:/*读取网络配置信息,p_data[0]=0x01为读取设置的网络配置,00为读取默认的,网络IP,子网掩码,网关,DNS服务器*/ { if(p_data[0] == 0x01) { len += gui_tjc_hmi_tx_text_display(1,1,(char *)&hmi_tx_buffer[len], "%d.%d.%d.%d", W5500.IP_Addr[0], W5500.IP_Addr[1], W5500.IP_Addr[2], W5500.IP_Addr[3]); len += gui_tjc_hmi_tx_text_display(1,2,(char *)&hmi_tx_buffer[len], "%d.%d.%d.%d", W5500.Sub_Mask[0], W5500.Sub_Mask[1], W5500.Sub_Mask[2], W5500.Sub_Mask[3]); len += gui_tjc_hmi_tx_text_display(1,3,(char *)&hmi_tx_buffer[len], "%d.%d.%d.%d", W5500.Gateway_IP[0], W5500.Gateway_IP[1], W5500.Gateway_IP[2], W5500.Gateway_IP[3]); len += gui_tjc_hmi_tx_text_display(1,4,(char *)&hmi_tx_buffer[len],"%s","5000"); }else if(p_data[0] == 0x00) { len += gui_tjc_hmi_tx_text_display(1,1,(char *)&hmi_tx_buffer[len],"%s","192.168.100.100"); len += gui_tjc_hmi_tx_text_display(1,2,(char *)&hmi_tx_buffer[len],"%s","255.255.255.0"); len += gui_tjc_hmi_tx_text_display(1,3,(char *)&hmi_tx_buffer[len],"%s","192.168.50.1"); len += gui_tjc_hmi_tx_text_display(1,4,(char *)&hmi_tx_buffer[len],"%s","5000"); } }break; case 0x02:/*无*/ { }break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if(HMI_PROTO_CMD_SET == cmd)/*设置*/ { switch(opa) { case 0x01:/*添加网络配置,并将网络配置信息存入flash*/ { u8 field_count = 0; u8 *current_pos = p_data; u8 ip_str[16], mask_str[16], gw_str[16], dns_str[16]; u8 ip_len, mask_len, gw_len, dns_len; /* 解析IP地址 */ for (i = 0; i < 16; i++) { if (current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { ip_len = i; memcpy(ip_str, current_pos, ip_len); ip_str[ip_len] = '\0'; current_pos += (i + 1); field_count++; break; } } /* 解析子网掩码 */ for (i = 0; i < 16; i++) { if (current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { mask_len = i; memcpy(mask_str, current_pos, mask_len); mask_str[mask_len] = '\0'; current_pos += (i + 1); field_count++; break; } } /* 解析网关 */ for (i = 0; i < 16; i++) { if (current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { gw_len = i; memcpy(gw_str, current_pos, gw_len); gw_str[gw_len] = '\0'; current_pos += (i + 1); field_count++; break; } } /* 解析DNS服务器 */ for (i = 0; i < 16; i++) { if (current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { dns_len = i; memcpy(dns_str, current_pos, dns_len); dns_str[dns_len] = '\0'; current_pos += (i + 1); field_count++; break; } } if (field_count == 4) { parse_ip_string(ip_str, ip_len, W5500.IP_Addr); parse_ip_string(mask_str, mask_len, W5500.Sub_Mask); parse_ip_string(gw_str, gw_len, W5500.Gateway_IP); } }break; case 0x02:/*无*/ { }break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } } /*设备配置界面 */ static void gui_tjc_hmi_device_config_send(u8 cmd,u8 opa,u8 *p_data) { #define DEVICES_PER_PAGE (8) u16 len = 0,i,j; u8 found_empty_slot = 0,enabled_device_count,field_count,page_num,remain_region_num; u8 empty_slot_index = 0; u8 *current_pos = NULL; app_leakage_sub_device_flash_data_t new_device; memset(hmi_tx_buffer,0,sizeof(hmi_tx_buffer)); if(HMI_PROTO_CMD_GET == cmd)/*获取数据*/ { switch(opa) { case 0x01:/*读取已存在的设备,显示区域,端口,设备ID,设备名,*/ { u8 page_device_indices[DEVICES_PER_PAGE] = {0}; /*存储当前页8个设备在app_leakage中的索引*/ u8 page_device_count = 0; /*当前页实际启用的设备数量*/ u8 current_enabled_index = 0; /*当前是第几个启用的设备*/ u8 device_index; /*计算启用的设备数量*/ enabled_device_count = 0; for(i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { if(leakage.sub_device_data[i].flash_data.state == ENABLE) { enabled_device_count++; } } /*计算总页数*/ page_num = enabled_device_count / DEVICES_PER_PAGE; remain_region_num = enabled_device_count % DEVICES_PER_PAGE; if(remain_region_num > 0) { page_num++; } /*确保页码在有效范围内*/ if(p_tjc_hmi->page.device_config_index >= page_num) { p_tjc_hmi->page.device_config_index = 0; } if(enabled_device_count == 0) { for(i = 0; i < DEVICES_PER_PAGE; i++) { len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], ""); len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], ""); } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer, len); return; } /*获取当前页的设备索引*/ for(i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM && page_device_count < DEVICES_PER_PAGE; i++) { if(leakage.sub_device_data[i].flash_data.state == ENABLE) { current_enabled_index++; /*判断这个设备是否在当前页*/ u8 device_page = (current_enabled_index - 1) / DEVICES_PER_PAGE; if(device_page == p_tjc_hmi->page.device_config_index) { page_device_indices[page_device_count] = i; page_device_count++; } } } if(page_device_count == 0) { /*当前页没有设备,发送空数据*/ len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); return; } /*显示当前页的设备信息*/ for(i = 0; i < page_device_count; i++) { device_index = page_device_indices[i]; /*区域名: t(i+1)_1 */ len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], "%s", leakage.sub_device_data[device_index].flash_data.region_name); /*端口号: t(i+1)_2 */ u8 com_port = leakage.sub_device_data[device_index].flash_data.com; if(com_port < 4) /*确保端口号在有效范围内*/ { len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], "%s", hmi_proto_string_com[com_port]); } else { len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], "未知"); } /*设备ID: t(i+1)_3 */ len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], "%d", leakage.sub_device_data[device_index].flash_data.modbus_id); /*设备名称: t(i+1)_4 */ len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], "%s", leakage.sub_device_data[device_index].flash_data.device_name); } /*如果当前页不足8个设备,清空剩余的设备显示位置*/ if(page_device_count < DEVICES_PER_PAGE) { for(i = page_device_count; i < DEVICES_PER_PAGE; i++) { /*清空区域名*/ len += gui_tjc_hmi_tx_text_display(i+1, 1, (char *)&hmi_tx_buffer[len], ""); /*清空端口号*/ len += gui_tjc_hmi_tx_text_display(i+1, 2, (char *)&hmi_tx_buffer[len], ""); /*清空设备ID*/ len += gui_tjc_hmi_tx_text_display(i+1, 3, (char *)&hmi_tx_buffer[len], ""); /*清空设备名称*/ len += gui_tjc_hmi_tx_text_display(i+1, 4, (char *)&hmi_tx_buffer[len], ""); } } }break; case 0x02: /*读取四个COM口的波特率*/ { u8 baud_vals[4]; for (i = 0; i < 4; i++) { baud_vals[i] = app_com.com[i].flash_data.baudrate; } len = 0; len += sprintf((char*)&hmi_tx_buffer[len], "cb0.val=%d", baud_vals[0]); for (i = 0; i < 3; i++) hmi_tx_buffer[len + i] = 0xFF; len += 3; len += sprintf((char*)&hmi_tx_buffer[len], "cb1.val=%d", baud_vals[1]); for (i = 0; i < 3; i++) hmi_tx_buffer[len + i] = 0xFF; len += 3; len += sprintf((char*)&hmi_tx_buffer[len], "cb2.val=%d", baud_vals[2]); for (i = 0; i < 3; i++) hmi_tx_buffer[len + i] = 0xFF; len += 3; len += sprintf((char*)&hmi_tx_buffer[len], "cb3.val=%d", baud_vals[3]); for (i = 0; i < 3; i++) hmi_tx_buffer[len + i] = 0xFF; len += 3; gui_tjc_hmi_data_send(hmi_tx_buffer, len); return; } break; case 0x03:/*翻页功能,每页显示8个设备*/ { enabled_device_count = 0; for (i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { if (leakage.sub_device_data[i].flash_data.state == ENABLE) { enabled_device_count++; } } page_num = enabled_device_count / DEVICES_PER_PAGE; remain_region_num = enabled_device_count % DEVICES_PER_PAGE; if (remain_region_num > 0) { page_num++; } if (page_num == 0) page_num = 1; if(0x01 == p_data[0]) /*下一页*/ { if(page_num - 1 <= p_tjc_hmi->page.device_config_index) { p_tjc_hmi->page.device_config_index = 0; } else { p_tjc_hmi->page.device_config_index++; } } else /*上一页*/ { if(0 == p_tjc_hmi->page.device_config_index) { p_tjc_hmi->page.device_config_index = page_num - 1; } else { p_tjc_hmi->page.device_config_index--; } } /*翻页后需要重新获取数据并显示,这里不直接发送数据*/ return; }break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } else if(HMI_PROTO_CMD_SET == cmd)/*设置*/ { switch(opa) { case 0x01: { found_empty_slot = 0; for(i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++) { if(leakage.sub_device_data[i].flash_data.state == DISABLE) { found_empty_slot = 1; empty_slot_index = i; break; } } if(!found_empty_slot) { /*设备数量已满*/ return; } field_count = 0; current_pos = p_data; memset(&new_device, 0, sizeof(new_device)); /*解析端口号*/ for(i = 0; i < 10; i++) { if(current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { if(i == 0) { /*端口号不能为空*/ return; } char port_str[10] = {0}; memcpy(port_str, current_pos, i); port_str[i] = '\0'; /*将字符串端口号转换为数值*/ if(strcmp(port_str, "COM1") == 0) { new_device.com = 0; } else if(strcmp(port_str, "COM2") == 0) { new_device.com = 1; } else if(strcmp(port_str, "COM3") == 0) { new_device.com = 2; } else if(strcmp(port_str, "COM4") == 0) { new_device.com = 3; } current_pos += (i + 1); field_count++; break; } } // /*解析波特率*/ // for(i = 0; i < 10; i++) // 波特率最大为115200 // { // if(current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) // { // if(i == 0) // { // /*波特率不能为空*/ // return; // } // char baud_str[10] = {0}; // memcpy(baud_str, current_pos, i); // baud_str[i] = '\0'; // /*将字符串波特率转换为数值*/ // if(strcmp(baud_str, "2400") == 0) // { // new_device.baudrate = 0; // } // else if(strcmp(baud_str, "4800") == 0) // { // new_device.baudrate = 1; // } // else if(strcmp(baud_str, "9600") == 0) // { // new_device.baudrate = 2; // } // else if(strcmp(baud_str, "115200") == 0) // { // new_device.baudrate = 3; // } // current_pos += (i + 1); // field_count++; // break; // } // } /*解析区域名*/ for(i = 0; i < APP_LEAKAGE_STRING_NANE_LEN; i++) { if(current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { memcpy(new_device.region_name, current_pos, i); new_device.region_name[i] = '\0'; current_pos += (i + 1); field_count++; break; } } /*解析设备ID */ for(i = 0; i < 10; i++) { if(current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { if(i == 0) { /*设备ID不能为空*/ return; } /*设备ID是数字字符串,转换为数值*/ char id_str[10] = {0}; memcpy(id_str, current_pos, i); id_str[i] = '\0'; new_device.modbus_id = atoi(id_str); current_pos += (i + 1); field_count++; break; } } /*解析设备名称*/ for(i = 0; i < APP_LEAKAGE_STRING_NANE_LEN; i++) { if(current_pos[i] == HMI_PROTO_ASCII_RX_DELINITER) { memcpy(new_device.device_name, current_pos, i); new_device.device_name[i] = '\0'; field_count++; break; } } /*相同id时覆盖之前的*/ if(field_count == 4) { for(u8 x = 0; x < APP_LEAKAGE_SUB_DEVICE_NUM; x++) { if (leakage.sub_device_data[x].flash_data.modbus_id == new_device.modbus_id) { new_device.state = ENABLE; new_device.baudrate = app_com.com[new_device.com].flash_data.baudrate; new_device.shield = UNBLOCKED; leakage.sub_device_data[x].flash_data = new_device; gui_tjc_hmi_save_device_info_to_w25q(); gui_tjc_hmi_class_update(); field_count++; } } } /*添加到设备列表*/ if(field_count == 4) { /*设置默认状态为启用*/ new_device.state = ENABLE; /*波特率设置*/ new_device.baudrate = app_com.com[new_device.com].flash_data.baudrate; new_device.shield = UNBLOCKED; /*添加到app_leakage的设备列表中*/ leakage.sub_device_data[empty_slot_index].flash_data = new_device; /*清空通道数据*/ memset(leakage.sub_device_data[empty_slot_index].ch_data, 0, sizeof(leakage.sub_device_data[empty_slot_index].ch_data)); /*保存到W25Q32*/ gui_tjc_hmi_save_device_info_to_w25q(); /*重新分类区域*/ gui_tjc_hmi_class_update(); // if (new_device.com < APP_COM_NUM && new_device.baudrate < 4) { // app_com.com[new_device.com].set.baud_rate( // &app_com.com[new_device.com], // new_device.baudrate // ); // } } else { /*发送错误响应*/ return; } }break; case 0x02:/*删除设备,将设备信息从w25q中删除*/ { u8 page_device_indices[8] = {0}; /*存储当前页8个设备在app_leakage中的索引*/ u8 page_device_count = 0; /*当前页实际启用的设备数量*/ u8 current_enabled_index = 0; /*当前是第几个启用的设备*/ for(i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM && page_device_count < DEVICES_PER_PAGE; i++) { if(leakage.sub_device_data[i].flash_data.state == ENABLE) { current_enabled_index++; /*判断这个设备是否在当前页*/ u8 device_page = (current_enabled_index - 1) / DEVICES_PER_PAGE; if(device_page == p_tjc_hmi->page.device_config_index) { page_device_indices[page_device_count] = i; page_device_count++; } } } if(page_device_count == 0) { /*当前页没有设备*/ return; } /*遍历8个选中框字节,删除被选中的设备(从后往前删除)*/ u8 deleted_count = 0; for(i = page_device_count; i > 0; i--) { u8 idx = i - 1; if(p_data[idx] == 0x01) { u8 actual_index = page_device_indices[idx]; // 直接使用原始索引 /*将后面的设备向前移动*/ for(j = actual_index; j < APP_LEAKAGE_SUB_DEVICE_NUM - 1; j++) { leakage.sub_device_data[j].flash_data = leakage.sub_device_data[j + 1].flash_data; } /*最后一个设备清空*/ memset(&leakage.sub_device_data[APP_LEAKAGE_SUB_DEVICE_NUM - 1].flash_data, 0, sizeof(app_leakage_sub_device_flash_data_t)); leakage.sub_device_data[APP_LEAKAGE_SUB_DEVICE_NUM - 1].flash_data.state = DISABLE; /*清空通道数据*/ memset(leakage.sub_device_data[APP_LEAKAGE_SUB_DEVICE_NUM - 1].ch_data, 0, sizeof(leakage.sub_device_data[APP_LEAKAGE_SUB_DEVICE_NUM - 1].ch_data)); deleted_count++; } } if(deleted_count > 0) { /*保存到W25Q32*/ gui_tjc_hmi_save_device_info_to_w25q(); /*重新分类区域*/ gui_tjc_hmi_class_update(); /*可选:发送确认响应*/ } else { /*没有选中任何设备*/ return; } }break; case 0x03: /*设置波特率,波特率1对应COM1的*/ { u8 *ptr = p_data; u8 baud_vals[APP_COM_NUM]; char temp_buf[10]; /*临时存储ASCII字符串*/ for (i = 0; i < APP_COM_NUM; i++) { u8 temp_len = 0; // 提取直到下一个0xAA分隔符 while (*ptr != HMI_PROTO_ASCII_RX_DELINITER && temp_len < sizeof(temp_buf) - 1) { temp_buf[temp_len++] = *ptr++; } if (*ptr != HMI_PROTO_ASCII_RX_DELINITER) { return; } temp_buf[temp_len] = '\0'; ptr++; // 跳过分隔符 // 将ASCII字符串转换为整数波特率 u32 baud_int = atoi(temp_buf); // 映射到枚举值 u8 enum_val; if (baud_int == 4800) enum_val = 0; else if (baud_int == 9600) enum_val = 1; else if (baud_int == 19200) enum_val = 2; else if (baud_int == 57600) enum_val = 3; else if (baud_int == 115200) enum_val = 4; else enum_val = 4; baud_vals[i] = enum_val; } /*设置每个COM的波特率*/ for (i = 0; i < APP_COM_NUM; i++) { if (app_com.com[i].flash_data.baudrate != baud_vals[i]) { app_com.com[i].flash_data.baudrate = baud_vals[i]; if (app_com.com[i].set.baud_rate) { app_com.com[i].set.baud_rate(&app_com.com[i], baud_vals[i]); } } } app_com.save_flah(); return; } break; default:return; } len = strlen((char *)hmi_tx_buffer); gui_tjc_hmi_data_send(hmi_tx_buffer,len); } } /*设置时间界面*/ static void gui_tjc_hmi_time_set_send(u8 cmd,u8 opa,u8 *p_data) { u16 i, len = 0; char temp_buf[5]; bsp_DS1302_Time_t new_time; if(HMI_PROTO_CMD_SET == cmd) /* 设置命令 */ { switch(opa) { case 0x01: /* 设置时间 */ { int idx = 0; /*数据索引*/ int field = 0; /*当前字段编号(0:年,1:月,2:日,3:时,4:分)*/ char temp_buf[5]; int value; while (field < 5) { int len = 0; /*收集当前字段的ASCII字符直到遇到分隔符0xAA*/ while (p_data[idx] != 0xAA) { if (len >= 4) { return; } temp_buf[len++] = p_data[idx++]; } if (len == 0) { return; } temp_buf[len] = '\0'; value = atoi(temp_buf); /* 根据字段序号赋值*/ switch (field) { case 0: new_time.Year = value % 2000; break; // 年份取后两位 case 1: new_time.Month = value; break; case 2: new_time.Day = value; break; case 3: new_time.Hour = value; break; case 4: new_time.Minute = value; break; } /*跳过当前分隔符0xAA,准备下一个字段*/ idx++; field++; } DS1302.Set(&new_time); } break; default: break; } } } /*屏幕指令解析*/ static void gui_tjc_hmi_communication_data_analysis(u8 *p_data, u16 len, void *rx_uart) { u8 cmd,data,gui_id,opa,*p_offset_data; u16 i,modbus_crc16,check_crc16; /*长度不足*/ if(len < 5) { return ; } /*检测帧头*/ if(p_data[0] != HMI_PROTO_FRAME_HEADER1 || p_data[1] != HMI_PROTO_FRAME_HEADER2) { return ; } /*校验位*/ check_crc16 = p_data[len-2] << 8 | p_data[len-1]; modbus_crc16 = modbus_lib_crc16(p_data,len-2); modbus_crc16 = (modbus_crc16 >> 8) | (modbus_crc16 << 8); if(modbus_crc16 != check_crc16) { return ; } /*CMD*/ cmd = p_data[2]; if(cmd != HMI_PROTO_CMD_GET && cmd != HMI_PROTO_CMD_SET) { return ; } gui_id = p_data[3]; /*gui_id*/ opa = p_data[4]; /*操作码*/ p_offset_data = &p_data[5]; /*附带数据*/ p_rx_uart = (bsp_uart_t *)rx_uart; /*串口指针*/ switch(gui_id) { case HMI_PROTO_GUI_MAIN : { gui_tjc_hmi_main_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_CURR_ALARM : { gui_tjc_hmi_curr_alarm_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_DETAIL_MAIN : { gui_tjc_hmi_detail_main_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_LOGIN : { gui_tjc_hmi_login_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_HISTORY_ALARM : { gui_tjc_hmi_history_alarm_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_TCP_CONFIG : { gui_tjc_hmi_tcp_config_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_DEVICE_CONFIG : { gui_tjc_hmi_device_config_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_HELP : { //gui_tjc_hmi_help_send(cmd,opa,p_offset_data); }break; case HMI_PROTO_GUI_TIME : { gui_tjc_hmi_time_set_send(cmd,opa,p_offset_data); } } }