Files
Leakage-Control/leakage_system/usr/gui/gui_tjc_hmi.c
chenzongxiong 7373c0ad95 update:
设备屏蔽功能
适配新版界面
2026-03-06 13:48:42 +08:00

2153 lines
82 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "GUI_tjc_hmi.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#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<HMI_PROTO_ASCII_TX_DELINITER_NUM;i++)
{
buffer[len + i] = HMI_PROTO_ASCII_TX_DELINITER;
}
va_end(arg);
return len + 3;
}
/*主界面响应*/
static void gui_tjc_hmi_main_send(u8 cmd,u8 opa,u8 *p_data)
{
/*每页显示的区域数量*/
#define MAIN_PAGE_SUB_DEVICE_NUM (4)
u16 len = 0,i,j,x,y,index;
u8 page_num,remain_region_num;
memset(hmi_tx_buffer,0,sizeof(hmi_tx_buffer));
/*计算页面数量*/
page_num = leakage.region_num / MAIN_PAGE_SUB_DEVICE_NUM;
remain_region_num = leakage.region_num % MAIN_PAGE_SUB_DEVICE_NUM;/*剩余区域数量*/
if(remain_region_num > 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;j<remain_region_num;j++)
{
index = p_tjc_hmi->page.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;j<MAIN_PAGE_SUB_DEVICE_NUM;j++)
{
index = p_tjc_hmi->page.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<APP_LEAKAGE_SUB_DEVICE_NUM;i++)
{
if(ENABLE != leakage.sub_device_data[i].flash_data.state)
{
continue ;
}
if(UNBLOCKED != leakage.sub_device_data[i].flash_data.shield)
{
continue ;
}
for(ch=0;ch<APP_LEAKAGE_SUB_DEVICE_CH_NUM;ch++)
{
u16 ch_state = leakage.sub_device_data[i].ch_data[ch].state;
if(ch_state & (APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT | APP_LEAKAGE_SUB_DEVICE_STATE_OPEN | APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE))
{
alarm_device_index[alarm_device_count] = i;
alarm_device_count++;
break;
}
}
}
if(alarm_device_count == 0)
{
return;
}
/*计算页面数量*/
page_num = alarm_device_count / REAL_ALARM_PAGE_NUM;
remain_alrm_device_num = alarm_device_count % REAL_ALARM_PAGE_NUM;
if(remain_alrm_device_num > 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;j<remain_alrm_device_num;j++)
{
index = p_tjc_hmi->page.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;ch<APP_LEAKAGE_SUB_DEVICE_CH_NUM;ch++)
{
if(leakage.sub_device_data[device_index].ch_data[ch].state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
{
comm_state = APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT;
break;
}
}
if(comm_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
{
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(ch=0;ch<APP_LEAKAGE_SUB_DEVICE_CH_NUM;ch++)
{
u16 ch_state = leakage.sub_device_data[device_index].ch_data[ch].state;
u16 ch_distance = leakage.sub_device_data[device_index].ch_data[ch].distance;
y = 4 + (ch * 3);
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],"正常");
}
y =5 + (ch * 3);
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],"正常");
}
y = 6 + (ch * 3);
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
{
for(j=0;j<REAL_ALARM_PAGE_NUM;j++)
{
index = p_tjc_hmi->page.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;ch<APP_LEAKAGE_SUB_DEVICE_CH_NUM;ch++)
{
if(leakage.sub_device_data[device_index].ch_data[ch].state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
{
comm_state = APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT;
break;
}
}
if(comm_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
{
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(ch=0;ch<APP_LEAKAGE_SUB_DEVICE_CH_NUM;ch++)
{
u16 ch_state = leakage.sub_device_data[device_index].ch_data[ch].state;
u16 ch_distance = leakage.sub_device_data[device_index].ch_data[ch].distance;
y = 4 + (ch * 3);
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],"正常");
}
y =5 + (ch * 3);
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],"正常");
}
y = 6 + (ch * 3);
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");
}
}
}
}
for (; j < REAL_ALARM_PAGE_NUM; j++)
{
x = j;
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], ""); // 设备ID
len += gui_tjc_hmi_tx_text_display(x + 1, 3, (char *)&hmi_tx_buffer[len], ""); // 设备名称
len += gui_tjc_hmi_tx_text_display(x + 1, 4, (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, 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, 7 + (ch * 3), (char *)&hmi_tx_buffer[len], "");
}
}
}break;
case 0x03:/*翻页*/
{
if(0x01 == p_data[0])
{
if(page_num - 1 <= p_tjc_hmi->page.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);
}
}
}