
/*
 *
 * Communication_can_base   can通信模块的基类,
 * 用户从这个基类继承, 初始化之后, 便可以自动进行通信
 *
 *
 *
 * */

#ifndef CAN_TEST_COMMUNICATION_CAN_BASE_H
#define CAN_TEST_COMMUNICATION_CAN_BASE_H

#include "../can_SDK/controlcan.h"
#include "../error_code/error_code.h"
#include "../tool/thread_safe_list.h"
#include "../tool/thread_condition.h"
#include "../tool/proto_tool.h"
#include "../communication_can/communication_can.pb.h"

#include <glog/logging.h>
#include <string>
#include <map>
#include <mutex>


//默认can通信的配置参数路径
#define COMMUNICATION_CAN_PARAMETER_PATH "/home/youchen/extra_space/agv_200731/src/robot_control/src/can_card/setting/communication_can.prototxt"

//can卡通道数量, 默认2个通道
#define CAN_PORT_NUMBER 			2
//can设备信息
struct Can_device
{
	int 		can_device_id;						//can设备ID, 自定义的(从prototxt导入)
	int			can_handle_id;						//can句柄ID, 系统自动分配, 从0开始, 往后++
	std::string can_serial_number;					//can设备条形码(20个char)
	int 		can_device_type;					//can设备类型, linux版本默认为4 ,  #define VCI_USBCAN2		4
	bool  		can_port_flag[CAN_PORT_NUMBER];		//can设备 2个通道口的使能标记位
	int 		can_baud_rate;						//can设备的波特率
};

//can消息
struct Can_message
{
	int 			can_device_id;			//can设备ID
	int  			can_port_id;			//can通道ID
	_VCI_CAN_OBJ	can_object;				//can消息结构体, SDK里面的
};


//can通信模块的基类,
class Communication_can_base
{
	//通信状态
	enum Communication_statu
	{
		COMMUNICATION_UNKNOW		=0,	        //通信状态 未知
		COMMUNICATION_READY			=1,			//通信状态 正常

		COMMUNICATION_FAULT			=3,         //通信状态 错误
	};


public:
	Communication_can_base();
	Communication_can_base(const Communication_can_base& other)= delete;
	Communication_can_base& operator =(const Communication_can_base& other)= delete;
	~Communication_can_base();

public://API functions
	//初始化 通信 模块。如下三选一
	virtual Error_manager communication_init();
	//初始化 通信 模块。从文件读取
	virtual Error_manager communication_init_from_protobuf(std::string prototxt_path);
	//初始化 通信 模块。从protobuf读取
	virtual Error_manager communication_init_from_protobuf(Communication_can_proto::Communication_can_parameter_all& communication_can_parameter_all);

	//反初始化 通信 模块。
	virtual Error_manager communication_uninit();

	//封装消息, 需要子类重载
	virtual Error_manager encapsulate_msg(Can_message* p_msg);

public://get or set member variable
	void set_analysis_cycle_time(unsigned int analysis_cycle_time);
	void set_encapsulate_cycle_time(unsigned int encapsulate_cycle_time);

protected:
	//启动can卡,
	virtual Error_manager can_run();
	//启动通信, run thread
	virtual Error_manager communication_run();

	//mp_receive_data_thread 接受线程执行函数，
	//receive_data_thread 内部线程负责接受消息
	void receive_data_thread();

	//检查消息是否有效, 判断这条消息是不是给我的.
	virtual Error_manager check_msg(Can_message* p_msg);

	//mp_analysis_data_thread 解析线程执行函数，
	//analysis_data_thread 内部线程负责解析消息
	void analysis_data_thread();

	//检查执行者的状态, 判断能否处理这条消息, 需要子类重载
	virtual Error_manager check_executer(Can_message* p_msg);

	//处理消息, 需要子类重载
	virtual Error_manager execute_msg(Can_message* p_msg);

	//mp_send_data_thread 发送线程执行函数，
	//send_data_thread 内部线程负责发送消息
	void send_data_thread();

	//mp_encapsulate_data_thread 封装线程执行函数，
	//encapsulate_data_thread 内部线程负责封装消息
	void encapsulate_data_thread();

	//定时封装发送消息, 一般为心跳和状态信息, 需要子类重载
	virtual Error_manager encapsulate_send_data();

public:




protected://member variable
	bool								m_initialization_flag;			//是否初始化的标记位

	std::map<int, Can_device>			m_can_device_map;				//can设备的map, 索引为设备ID
	std::mutex 							m_mutex;						//can设备的锁

	//通信状态
	Communication_statu 				m_communication_statu;			//通信状态

	//接受模块,
	Thread_safe_list<Can_message*>		m_receive_data_list; 			//接受的list容器
	std::thread*						mp_receive_data_thread;    		//接受的线程指针
	Thread_condition					m_receive_condition;			//接受的条件变量
	std::thread*						mp_analysis_data_thread;    	//解析的线程指针
	Thread_condition					m_analysis_data_condition;		//解析的条件变量
	unsigned int 						m_analysis_cycle_time;			//自动解析的时间周期

	//发送模块,
	Thread_safe_list<Can_message*>		m_send_data_list;				//发送的list容器
	std::thread*						mp_send_data_thread;    		//发送的线程指针
	Thread_condition					m_send_data_condition;			//发送的条件变量
	std::thread*						mp_encapsulate_data_thread;    	//封装的线程指针
	Thread_condition					m_encapsulate_data_condition;	//封装的条件变量
	unsigned int 						m_encapsulate_cycle_time;		//自动封装的时间周期

};



#endif //CAN_TEST_COMMUNICATION_CAN_BASE_H
