//
// Created by huli on 2021/12/23.
//

#include "led_protocol.h"

Led_protocol::Led_protocol()
{

}

Led_protocol::~Led_protocol()
{
	led_protocol_uninit();
}

//led通信协议初始化, area_size必须为1~5
Error_manager Led_protocol::led_protocol_init(int area_size)
{
	led_communication_msg_init(area_size);
	m_encapsulate_flag = false;

	return Error_code::SUCCESS;
}

Error_manager Led_protocol::led_protocol_uninit()
{
	return Error_code::SUCCESS;
}

Error_manager Led_protocol::led_protocol_reset()
{
	m_encapsulate_flag = false;
	//清除缓存后, 直接初始化可以重置所有...
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.clear();
	led_protocol_init();

	return Error_code::SUCCESS;
}

Error_manager Led_protocol::led_protocol_delete(int area_index)
{
	if  ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find(area_index) !=
		  m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end())
	{
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.erase(area_index);
	}
	return Error_code::SUCCESS;

}


//创建led消息, 参数输入需要显示的字符串即可
std::string Led_protocol::create_led_message(int area_index, std::string show_string, unsigned short x, unsigned short y, unsigned short width, unsigned short heigth)
{
	led_communication_area_create(area_index);
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_show_string = show_string;

	unsigned short t_area_x = 0x8000+x;	//区域 X 坐标,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[3] = t_area_x;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[4] = t_area_x>>8;
	unsigned short t_area_y = y;	//区域 Y 坐标,以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[5] = t_area_y;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[6] = t_area_y>>8;

	unsigned short t_area_width = 0x8000+width;	//区域宽度,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[7] = t_area_width;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[8] = t_area_width>>8;
	unsigned short t_area_height = heigth;	//区域高度,以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[9] = t_area_height;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[10] = t_area_height>>8;

	return get_led_msg_total_string();
}

//获取led协议封装后的最终消息, 这个结果就可以直接tcp发送了
std::string Led_protocol::get_led_msg_total_string()
{
	led_communication_total_encapsulate();
	return m_led_communication_msg.m_total_string;
}
//获取led协议封装后的最终消息, 这个结果就可以直接tcp发送了
std::string Led_protocol::get_led_msg_total_string(int area_index)
{
	led_communication_total_encapsulate(area_index);
	return m_led_communication_msg.m_total_string;
}

//设置显示的内容
Error_manager Led_protocol::set_show_string(int area_index, std::string show_string)
{
	led_communication_area_create(area_index);
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_show_string = show_string;
	return Error_code::SUCCESS;
}

//设置显示的矩形框, 单位像素点, (注:一个汉字为16*16像素)
Error_manager Led_protocol::set_show_rectangle(int area_index, unsigned short x, unsigned short y, unsigned short width, unsigned short heigth)
{
	led_communication_area_create(area_index);
	unsigned short t_area_x = 0x8000+x;	//区域 X 坐标,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[3] = t_area_x;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[4] = t_area_x>>8;
	unsigned short t_area_y = y;	//区域 Y 坐标,以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[5] = t_area_y;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[6] = t_area_y>>8;

	unsigned short t_area_width = 0x8000+width;	//区域宽度,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[7] = t_area_width;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[8] = t_area_width>>8;
	unsigned short t_area_height = heigth;	//区域高度,以像素点为单位
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[9] = t_area_height;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[10] = t_area_height>>8;

	return Error_code::SUCCESS;
}

//设置显示的行间距
Error_manager Led_protocol::set_lines_sizes(int area_index, unsigned char lines_sizes)
{
	led_communication_area_create(area_index);
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[12] = lines_sizes;
	return Error_code::SUCCESS;
}

//设置显示动态区运行模式
Error_manager Led_protocol::set_run_mode(int area_index, unsigned char run_mode, unsigned short time_out)
{
	led_communication_area_create(area_index);
	/*动态区运行模式
		0—动态区数据循环显示。
		1—动态区数据显示完成后静止显示最后一页数
		据。
		2—动态区数据循环显示,超过设定时间后数据仍
		未更新时不再显示
		3—动态区数据循环显示,超过设定时间后数据仍
		未更新时显示 Logo 信息,Logo 信息即为动态区域
		的最后一页信息
		4—动态区数据顺序显示,显示完最后一页后就不
		再显示
		5—动态区数据顺序显示,超过设定次数后数据仍
		未更新时不再显示*/
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[13] = run_mode;
	//动态区数据超时时间,单位为 秒/次数 (若RunMode=5,则表示更新次数), , 默认0x0002
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[14] = time_out;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[15] = time_out>>8;
	return Error_code::SUCCESS;
}

//设置显示的排版方式
Error_manager Led_protocol::set_type_setting(int area_index, unsigned char type_setting)
{
	led_communication_area_create(area_index);
	/*	排 版 方 式 ( 上 下 左 右 有 优 先 级 )
	当 ExtendParaLen > 0,才发送该字节,否则不发送
	0:表示先从左往右,再从上往下
	1:表示先从右往左,再从上往下
	2:表示先从上往下,再从左往右
	3:表示先从上往下,再从右往左*/
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[17] = type_setting;
	return Error_code::SUCCESS;
}

//设置显示的对齐方式
Error_manager Led_protocol::set_text_alignment(int area_index, unsigned char text_alignment)
{
	led_communication_area_create(area_index);
	/*	行(上下左右)字对齐方式
	Bit1 	Bit0
	0		0 ----左对齐(左右 默认)
	0		1 ----右对齐(左右)
	1		0 ----居中对齐(左右)
	Bit3 	Bit2
	0		0 ----上对齐(上下 默认)
	0		1 ----下对齐(上下)
	1		0 ----居中对齐(上下)*/
	unsigned char t_text_alignment = text_alignment;
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[18] = t_text_alignment;
	return Error_code::SUCCESS;
}

//设置显示 是否单行显示 是否自动换行
Error_manager Led_protocol::set_line_mode(int area_index, unsigned char single_line, unsigned char new_line)
{
	led_communication_area_create(area_index);
	/*是否单行显示
0x01——单行显示
0x02——多行显示*/
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[19] = single_line;
	/*是否自动换行
0x01——不自动换行,显示数据在换行时必须插入
换行符
0x02——自动换行,显示内容不需要换行符,但是
只能使用统一的中文字体和英文字体*/
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[20] = new_line;

	return Error_code::SUCCESS;
}


//设置显示方式, 文字移动的方式
Error_manager Led_protocol::set_display_mode(int area_index, unsigned char display_mode)
{
	led_communication_area_create(area_index);
	/*显示方式,其定义如下:
0x01——静止显示
0x02——快速打出
0x03——向左移动
0x04——向右移动
0x05——向上移动
0x06——向下移动*/
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[21] = display_mode;
	return Error_code::SUCCESS;
}

//设置显示速度 显示特技停留时间
Error_manager Led_protocol::set_speed(int area_index, unsigned char speed, unsigned char stay_time)
{
	led_communication_area_create(area_index);
//显示速度, 默认0x00,   从0x00~0x18 数字越小速度越快
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[23] = speed;
//显示特技停留时间,单位为 0.5s, 默认0x0a, 如:0x0A,则停留5秒
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[24] = stay_time;


	return Error_code::SUCCESS;
}







//led通信的区域数据, 新建, area_size为更新区域的索引编号//map里面没有就新建一个, 有就什么都不做.
Error_manager Led_protocol::led_communication_area_create(int area_index)
{
	//map里面没有就新建一个, 有就什么都不做.
	if ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find(area_index) ==
		 m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end() )
	{
		unsigned short t_area_data_len = 0x0000;	//区域的数据长度,就是 29-2+m_show_string.length(), 后面再赋值
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[0] = t_area_data_len;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[1] = t_area_data_len>>8;


		unsigned char t_area_type = 0x00;	//区域类型, 默认0x00
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[2] = t_area_type;

		unsigned short t_area_x = 0x8000;	//区域 X 坐标,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[3] = t_area_x;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[4] = t_area_x>>8;
		unsigned short t_area_y = 0x0000;	//区域 Y 坐标,以像素点为单位
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[5] = t_area_y;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[6] = t_area_y>>8;

		unsigned short t_area_width = 0x8020;	//区域宽度,默认以字节(8 个像素点)为单位, 高字节最高位为 1 时,表示以像素点为单位
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[7] = t_area_width;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[8] = t_area_width>>8;
		unsigned short t_area_height = 0x0020;	//区域高度,以像素点为单位
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[9] = t_area_height;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[10] = t_area_height>>8;
		//这里的宽高默认为0x20和0x20, 即为32*32, 可以显示4个汉字.(每个汉字为16*16, 字母为8*16)

		unsigned char t_area_index = area_index;	//动态区域编号
		//注意:该参数只对动态区有效,其他区域为默认值,动态区必须统一编号,编号从 0 开始递增。
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[11] = t_area_index;

		unsigned char t_lines_sizes = 0x00;			//行间距, 默认0x00
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[12] = t_lines_sizes;

		unsigned char t_run_mode = 0x00;	//动态区运行模式, 默认0x00
		/*动态区运行模式
		0—动态区数据循环显示。
		1—动态区数据显示完成后静止显示最后一页数
		据。
		2—动态区数据循环显示,超过设定时间后数据仍
		未更新时不再显示
		3—动态区数据循环显示,超过设定时间后数据仍
		未更新时显示 Logo 信息,Logo 信息即为动态区域
		的最后一页信息
		4—动态区数据顺序显示,显示完最后一页后就不
		再显示
		5—动态区数据顺序显示,超过设定次数后数据仍
		未更新时不再显示*/
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[13] = t_run_mode;

		unsigned short t_timeout = 0x0002;	//动态区数据超时时间,单位为 秒/次数 (若RunMode=5,则表示更新次数), , 默认0x0002
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[14] = t_timeout;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[15] = t_timeout>>8;

		unsigned char t_extend_para_len = 0x00;	//拓展位个数, 默认0x00, 如:0x0A,则拓展位为 10 位,
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[16] = t_extend_para_len;

		unsigned char t_type_setting = 0x00;	//排 版 方 式, 默认0x00,
		/*	排 版 方 式 ( 上 下 左 右 有 优 先 级 )
			当 ExtendParaLen > 0,才发送该字节,否则不发送
			0:表示先从左往右,再从上往下
			1:表示先从右往左,再从上往下
			2:表示先从上往下,再从左往右
			3:表示先从上往下,再从右往左*/
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[17] = t_type_setting;

		unsigned char t_text_alignment = 0x00;	//字体对齐方式/区域数据排版, 默认0x00, 如:0x00, 左对齐 , 上对齐
		/*	行(上下左右)字对齐方式
			Bit1 	Bit0
			0		0 ----左对齐(左右 默认)
			0		1 ----右对齐(左右)
			1		0 ----居中对齐(左右)
			Bit3 	Bit2
			0		0 ----上对齐(上下 默认)
			0		1 ----下对齐(上下)
			1		0 ----居中对齐(上下)*/
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[18] = t_text_alignment;

		unsigned char t_single_line = 0x02;	//是否单行显示, 默认0x02,      0x01——单行显示  0x02——多行显示
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[19] = t_single_line;

		unsigned char t_new_line = 0x01;	//是否自动换行, 默认0x01,
		/*是否自动换行
		0x01——不自动换行,显示数据在换行时必须插入
		换行符
		0x02——自动换行,显示内容不需要换行符,但是
		只能使用统一的中文字体和英文字体*/
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[20] = t_new_line;

		unsigned char t_display_mode = 0x01;	//显示方式, 默认0x01, 如果显示内容较多, 就需要滚动显示, 就设为向上移动0x05
		/*显示方式,其定义如下:
		0x01——静止显示
		0x02——快速打出
		0x03——向左移动
		0x04——向右移动
		0x05——向上移动
		0x06——向下移动*/
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[21] = t_display_mode;

		unsigned char t_exit_mode = 0x00;	//退出方式, 默认0x00,
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[22] = t_exit_mode;

		unsigned char t_speed = 0x00;	//显示速度, 默认0x00,   从0x00~0x18 数字越小速度越快
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[23] = t_speed;

		unsigned char t_stay_time = 0x0a;	//显示特技停留时间,单位为 0.5s, 默认0x0a, 如:0x0A,则停留5秒
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[24] = t_stay_time;

		unsigned int t_show_string_len = 0x00000000;	//数据长度(包括换行,颜色等转义参数), 就是 m_show_string.length(), 后面再赋值
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[25] = t_show_string_len;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[26] = t_show_string_len>>8;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[27] = t_show_string_len>>16;
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_area_head[28] = t_show_string_len>>24;

	}

	return Error_code::SUCCESS;
}
//led通信的控制指令, 初始化, area_size为更新区域的数量, 默认为0
Error_manager Led_protocol::led_communication_cmd_init(int area_size)
{
	//led通信的区域数据, 在修改里面具体参数的时候初始化
	//多次修改也只初始化一次

	//初始化 led通信的控制指令, 结构体
	//0xA3 0x06 表示 发送实时显示区域数据
	unsigned char t_cmd_group = 0xA3;	//命令分组编号
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[0] = t_cmd_group;
	unsigned char t_cmd = 0x06;	//命令编号
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[1] = t_cmd;

	unsigned char t_response = 0x01;	//是否要求控制器回复, 默认0x01
/*	是否要求控制器回复。
	0x01——控制器必须回复
	0x02——控制器不必回复*/
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[2] = t_response;

	unsigned char t_process_mode = 0x00;	//处理模式, 默认0x00
/*	当该字节为 0 时,收到动态信息后不再进行清区域
	和初始化区域的操作,当该字节为 1 时,收到动态
	信息后需要进行清区域和初始化区域的操作。*/
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[3] = t_process_mode;

	unsigned char t_reserved = 0x00;	//此处保留1个byte
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[4] = t_reserved;

	unsigned char t_delete_area_num = 0x00;	//要删除的区域个数, 默认0x00
/*	要删除的区域个数。
	注意:如果该值为 0xFF,则删除所有动态区数据。
	如果该值为 0x00,则不删除区域。*/
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[5] = t_delete_area_num;

	unsigned char t_updata_area_num = area_size;	//要更新的区域个数, 默认0x00
/*	要删除的区域个数。
	注意:如果该值为 0xFF,则删除所有动态区数据。
	如果该值为 0x00,则不删除区域。*/
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[6] = t_updata_area_num;

	return Error_code::SUCCESS;
}
//led通信的物理传输层, 初始化, area_size为更新区域的数量, 默认为0
Error_manager Led_protocol::led_communication_msg_init(int area_size)
{
	led_communication_cmd_init(area_size);

	//初始化 led通信的物理传输层, 结构体
	memset(m_led_communication_msg.m_frame_head, 0xA5, 8);	//帧头, 默认8个0xA5

	unsigned short t_dst_addr = 0xFFFE;	//屏地址, 默认0xFFFE
/*	屏地址。
	在 PHY 层,广播地址定义如下:
	0xFFFF 为广播地址 1,此种模式下,控制器不返回
	数据,其可用于广播校时等命令。
	0xFFFE 为广播地址 2,此种模式主要用于广播设置
	屏参,控制器需返回数据。在返回的数据帧中,地
	址也应为 0XFFFE。
	0x8000~0xDFFF 地址为保留地址,对于物理层类型
	为 TCP/IP 或 GPRS 这种不需要处理 DstAddr 的,可
	将其目标地址设置为这个范围中的一个,默认设置
	地址为 0x8000。*/
	m_led_communication_msg.m_frame_configuration[0] = t_dst_addr;
	m_led_communication_msg.m_frame_configuration[1] = t_dst_addr>>8;

	unsigned short t_src_addr = 0x8000;	//屏地址, 默认0x8000
/*	源地址,几个特殊地址定义如下:
	PC 客户端软件从 0x8000 开始,范围为
	0x8000~0xDFFF,用来代表不同客户端软件;
	0xE000~0xFFFE 为保留地址*/
	m_led_communication_msg.m_frame_configuration[2] = t_src_addr;
	m_led_communication_msg.m_frame_configuration[3] = t_src_addr>>8;

	unsigned char t_reserved = 0x00;	//此处保留3个byte
	m_led_communication_msg.m_frame_configuration[4] = t_reserved;
	m_led_communication_msg.m_frame_configuration[5] = t_reserved;
	m_led_communication_msg.m_frame_configuration[6] = t_reserved;

	unsigned char t_option = 0x00;	//选项, 默认0x00
/*	当该字节的 BIT0 为 1 时,需要发送接下来的 16 字
	节 BarCode,这么做是为了便于在线设置控制器 IP.
	反之,当该字节的 BIT0 为 0 时,不需要发送接下来
	的 16 字节 BarCode.
	注意:
	1. 只有设置 IP 命令需要将该字节的 BIT0 设置为 1
	2. 上位机需要通过网络搜索命令来获取当前局域网
	内所有控制卡的 BarCode*/
	m_led_communication_msg.m_frame_configuration[7] = t_option;

	unsigned char t_check_mode = 0x00;	//校验模式, 默认0x00
/*	校验值共两个字节
	当该字节为 0 时,采用 CRC16 方式
	当该字节为 1 时,采用和校验的方式,仅保留最低
	位两个字节,采用小端模式
	当该字节为 2 时,无校验,校验字节可以为任意值*/
	m_led_communication_msg.m_frame_configuration[8] = t_check_mode;

	unsigned char t_display_mode = 0x00;	//显示模式, 默认0x00
/*	0x00:普通模式,动态区与节目可同时显示,但各
	区域不可重叠。
	0x01:动态模式,优先显示动态区,无动态区则显
	示节目,动态区与节目区可重叠。
	注:特殊动态区不支持动态模式。*/
	m_led_communication_msg.m_frame_configuration[9] = t_display_mode;

	unsigned char t_device_type = LED_DEVICE_TYPE;	//设备类型, 默认0x63
/*	用于区分网络中不同的设备类型,定义如下:
	0x51——BX-5K1
	0x58——BX-5K2
	0x53——BX-5MK2
	0x54——BX-5MK1
	0x61——BX-6K1
	与 5K1 (0x51)兼容
	0x62——BX-6K2
	与 5MK1 (0x54) 兼容
	0x63——BX-6K3
	与 5K2,5MK2 (0x53/0x58)兼容
	0x64——BX-6K1-YY
	0x65——BX-6K2-YY
	0x66——BX-6K3-YY*/
	m_led_communication_msg.m_frame_configuration[10] = t_device_type;

	unsigned char t_protocol_version = 0x02;	//协议版本号, 默认0x02
	//协议版本号,用于区分控制卡使用的协议
	m_led_communication_msg.m_frame_configuration[11] = t_protocol_version;

	unsigned short t_data_len = 0;	//数据域长度(不包括帧头、帧尾、帧校验和包头), 这里指通信指令, 后面再赋值
	m_led_communication_msg.m_frame_configuration[12] = t_data_len;
	m_led_communication_msg.m_frame_configuration[13] = t_data_len>>8;


	unsigned short t_crc = 0;	//crc校验码, 包校验为包头数据和数据域的校验值, 后面再赋值
	m_led_communication_msg.m_frame_crc[0] = t_crc;
	m_led_communication_msg.m_frame_crc[1] = t_crc>>8;

	memset(m_led_communication_msg.m_frame_tail, 0x5A, 1);	//帧尾, 默认1个0x5A

	return Error_code::SUCCESS;
}

//led通信的区域数据, 通过协议转化, m_led_communication_area 封装成 m_total_string
Error_manager Led_protocol::led_communication_area_encapsulate()
{
	for (auto iter = m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.begin();
		 iter != m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end(); ++iter)
	{
		//1.填写区域数据长度, 后面的27byte加显示字符串
		unsigned short t_area_data_len = 29-2+iter->second.m_show_string.length();
		iter->second.m_area_head[0] = t_area_data_len;
		iter->second.m_area_head[1] = t_area_data_len>>8;

		//2.填写显示字符串长度
		unsigned int t_show_string_len = iter->second.m_show_string.length();
		iter->second.m_area_head[25] = t_show_string_len;
		iter->second.m_area_head[26] = t_show_string_len>>8;
		iter->second.m_area_head[27] = t_show_string_len>>16;
		iter->second.m_area_head[28] = t_show_string_len>>24;

		//3.汇总字符串
		iter->second.m_total_string = std::string( (char*)iter->second.m_area_head, 29);
		iter->second.m_total_string += iter->second.m_show_string;
	}

	return Error_code::SUCCESS;
}

//led通信的区域数据, 通过协议转化, m_led_communication_area 封装成 m_total_string
Error_manager Led_protocol::led_communication_area_encapsulate(int area_index)
{
	if ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find(area_index) !=
		 m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end())
	{
		auto & second = m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index];
		//1.填写区域数据长度, 后面的27byte加显示字符串
		unsigned short t_area_data_len = 29-2+second.m_show_string.length();
		second.m_area_head[0] = t_area_data_len;
		second.m_area_head[1] = t_area_data_len>>8;

		//2.填写显示字符串长度
		unsigned int t_show_string_len = second.m_show_string.length();
		second.m_area_head[25] = t_show_string_len;
		second.m_area_head[26] = t_show_string_len>>8;
		second.m_area_head[27] = t_show_string_len>>16;
		second.m_area_head[28] = t_show_string_len>>24;

		//3.汇总字符串
		second.m_total_string = std::string( (char*)second.m_area_head, 29);
		second.m_total_string += second.m_show_string;
	}

	return Error_code::SUCCESS;
}

//led通信的控制指令, 通过协议转化, m_led_communication_cmd 封装成 m_total_string
Error_manager Led_protocol::led_communication_cmd_encapsulate()
{
	//1.填写更新区域的个数
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[6] =
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.size();

	//2.汇总字符串
	m_led_communication_msg.m_led_communication_cmd.m_total_string =
	std::string( (char*)m_led_communication_msg.m_led_communication_cmd.m_cmd_head, 7);
	for (auto iter = m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.begin();
		 iter != m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end(); ++iter)
	{
		m_led_communication_msg.m_led_communication_cmd.m_total_string += iter->second.m_total_string;
	}
	return Error_code::SUCCESS;
}
//led通信的控制指令, 通过协议转化, m_led_communication_cmd 封装成 m_total_string
Error_manager Led_protocol::led_communication_cmd_encapsulate(int area_index)
{
	//1.填写更新区域的个数
	m_led_communication_msg.m_led_communication_cmd.m_cmd_head[6] = 1;

	//2.汇总字符串
	m_led_communication_msg.m_led_communication_cmd.m_total_string =
	std::string( (char*)m_led_communication_msg.m_led_communication_cmd.m_cmd_head, 7);
	if ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find(area_index) !=
		 m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end())
	{
		m_led_communication_msg.m_led_communication_cmd.m_total_string +=
		m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map[area_index].m_total_string;
	}
	return Error_code::SUCCESS;
}
//led通信的物理传输层, 通过协议转化, m_led_communication_msg 封装成 m_total_string
Error_manager Led_protocol::led_communication_msg_encapsulate()
{
	//1.填写指令的长度
	unsigned short t_data_len = m_led_communication_msg.m_led_communication_cmd.m_total_string.length();
	m_led_communication_msg.m_frame_configuration[12] = t_data_len;
	m_led_communication_msg.m_frame_configuration[13] = t_data_len>>8;

	//2.计算crc校验码, 需要使用包头和指令
	std::string t_result_src = std::string((char*)m_led_communication_msg.m_frame_configuration, 14);
	t_result_src += m_led_communication_msg.m_led_communication_cmd.m_total_string;
	unsigned short t_crc = crc16((unsigned char *)t_result_src.c_str(), t_result_src.length());
	m_led_communication_msg.m_frame_crc[0] = t_crc;
	m_led_communication_msg.m_frame_crc[1] = t_crc>>8;

	//3.字符转义, 需要使用包头和指令和crc校验码
	t_result_src += std::string( (char*)m_led_communication_msg.m_frame_crc, 2);
	int t_result_src_length=t_result_src.length();
	unsigned char t_result_dst[1024] = {0};//转义后的临时缓存, 长度上限1024
	int t_result_dst_length=0;
	character_escape(t_result_dst, &t_result_dst_length, (unsigned char *)t_result_src.c_str(), &t_result_src_length);

	//4.汇总字符串
	std::string str1 = std::string((char*)m_led_communication_msg.m_frame_head, 8);
	std::string str2 = std::string((char*)t_result_dst, t_result_dst_length);
	std::string str3 = std::string((char*)m_led_communication_msg.m_frame_tail, 1);
	m_led_communication_msg.m_total_string = str1 + str2 + str3;

	return Error_code::SUCCESS;
}

//led通信的物理传输层, 通过协议转化, m_led_communication_msg 封装成 m_total_string
Error_manager Led_protocol::led_communication_msg_encapsulate(int area_index)
{
	return led_communication_msg_encapsulate();
}

//led通信协议的整体封装
Error_manager Led_protocol::led_communication_total_encapsulate()
{
	if ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.size() <=0 )
	{
		m_encapsulate_flag = false;
		m_led_communication_msg.m_total_string.clear();
		return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
							 " fun error m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.size() <=0");
	}
	led_communication_area_encapsulate();
	led_communication_cmd_encapsulate();
	led_communication_msg_encapsulate();
	m_encapsulate_flag = true;
	return Error_code::SUCCESS;
}

//led通信协议的整体封装
Error_manager Led_protocol::led_communication_total_encapsulate(int area_index)
{
	if ( m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find(area_index) ==
	m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.end() )
	{
		m_encapsulate_flag = false;
		m_led_communication_msg.m_total_string.clear();
		return Error_manager(Error_code::ERROR, Error_level::MINOR_ERROR,
							 " fun error m_led_communication_msg.m_led_communication_cmd.m_led_communication_area_map.find() error ");
	}
	led_communication_area_encapsulate(area_index);
	led_communication_cmd_encapsulate(area_index);
	led_communication_msg_encapsulate(area_index);
	m_encapsulate_flag = true;
	return Error_code::SUCCESS;
}

//crc校验码
unsigned short Led_protocol::crc16(unsigned char * data,int size)
{
	unsigned char data_t ;
	unsigned short crc,i,j;
	crc = i = j = 0;
	if(data == NULL)
	{
		return 0;
	}
	for(j=0;j<size;j++)
	{
		data_t = data[j];
		crc = (data_t ^ crc);
		for(i=0;i<8;i++)
		{
			if((crc&0x1)==1)
			{
				crc = (crc >> 1) ^ 0xA001;
			}
			else
			{
				crc >>= 1;
			}
		}
	}
	return crc;
}

//字符转义
void Led_protocol::character_escape(unsigned char * p_dst, int * p_dst_length, unsigned char * p_src, int * p_src_length)
{
/*	字符转义
	◆ 封帧中遇到 0xA5,则将之转义为 0xA6,0x02;如遇到 0xA6,则将之转义为 0xA6,0x01 。
	◆ 封帧中遇到 0x5A,则将之转义为 0x5B,0x02;如遇到 0x5B,则将之转义为 0x5B,0x01 。
	◆ 解帧过程如果遇到连续两个字节为 0xA6, 0x02 ,则反转义为 0xA5 。
	◆ 解帧过程如果遇到连续两个字节为 0xA6, 0x01 ,则反转义为 0xA6 。
	◆ 解帧过程如果遇到连续两个字节为 0x5B, 0x02 ,则反转义为 0x5A。
	◆ 解帧过程如果遇到连续两个字节为 0x5B, 0x01 ,则反转义为 0x5B。
	注意:封帧过程中,所涉及校验的数据皆是转义之前的数据,所涉及的数据长度皆是转义之前的数据
	长度。
*/
	if ( p_dst == NULL || p_src == NULL)
	{
		return;
	}
	int i=0;
	int j=0;
	for (i = 0; i < *p_src_length; ++i)
	{
		if ( p_src[i] == 0xA5 )
		{
			p_dst[j] = 0xA6;
			p_dst[j+1] = 0x02;
			j+=2;
		}
		else if ( p_src[i] == 0xA6 )
		{
			p_dst[j] = 0xA6;
			p_dst[j+1] = 0x01;
			j+=2;
		}
		else if ( p_src[i] == 0x5A )
		{
			p_dst[j] = 0x5B;
			p_dst[j+1] = 0x02;
			j+=2;
		}
		else if ( p_src[i] == 0x5B )
		{
			p_dst[j] = 0x5B;
			p_dst[j+1] = 0x01;
			j+=2;
		}
		else
		{
			p_dst[j] = p_src[i];
			j++;
		}
	}
	*p_dst_length = j;
	return;
}
//
////led通信的物理传输层, 通过协议转化, m_led_communication_msg -->> m_led_communication_string
//Error_manager Led_protocol::led_communication_encapsulate()
//{
//	unsigned char t_result_src[1024] = {0};//转义前的临时缓存, 长度上限1024
//	unsigned char t_result_dst[1024] = {0};//转义后的临时缓存, 长度上限1024
//	int t_result_src_length=0;
//	int t_result_dst_length=0;
//	memcpy(t_result_src+t_result_src_length, m_led_communication_msg.m_frame_configuration, 14);
//	t_result_src_length += 14;
//	memcpy(t_result_src+t_result_src_length, m_led_communication_msg.m_led_communication_cmd.m_total_string.c_str(), m_led_communication_msg.m_led_communication_cmd.m_total_string.length());
//	t_result_src_length += m_led_communication_msg.m_led_communication_cmd.m_total_string.length();
//	memcpy(t_result_src+t_result_src_length, m_led_communication_msg.m_frame_crc, 2);
//	t_result_src_length += 2;
//
//	//字符转义
//	character_escape(t_result_dst, &t_result_dst_length, t_result_src, &t_result_src_length);
//
//	std::string str1 = std::string((char*)m_led_communication_msg.m_frame_head, 8);
//	std::string str2 = std::string((char*)t_result_dst, t_result_dst_length);
//	std::string str3 = std::string((char*)m_led_communication_msg.m_frame_tail, 1);
//	m_led_communication_msg.m_total_string = str1 + str2 + str3;
//
//	return Error_code::SUCCESS;
//}
//







