@startuml

title 电子围栏类图

class async_client
{
    +Async_Client(boost::asio::io_service &io_service, boost::asio::ip::tcp::endpoint endpoint, fundata_t fundata_, void *p)//构造函数
    +bool client_connection_status()//连接状态判断
    +bool client_initialize_status()//初始化状态判断
    +bool initialize(bool with_reconnection = true)//初始化函数
    +bool close()//断开连接

    +std::atomic<bool> mb_exit //客户端退出标志
    -std::thread *m_connection_check_thread;// 连接状态主动检查线程
}

class wj_716_lidar_protocol
{  
    +Wj_716_lidar_protocol();// 构造
    +~Wj_716_lidar_protocol();// 析构
    +Error_manager initialize(wj::wjLidarParams params);//初始化函数
    +Error_manager data_process(const char *data, const int reclen);// 数据处理
    +Error_manager protocol(const char *data, const int len);// 万集通信协议
    +Error_manager on_recv_process(char *data, int len);// 接收消息
    +Error_manager check_xor(char *recvbuf, int recvlen);// 消息完整性检查
    +bool get_initialize_status();// 获取初始化状态
    +Error_manager get_scan_points(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out);// 获取扫描点云
    +std::chrono::steady_clock::time_point get_scan_time();// 获取扫描点云更新时间点
}

class wj_lidar_encapsulation
{
    +Wj_lidar_encapsulation();// 无参构造函数
    +~Wj_lidar_encapsulation();// 析构函数
    +Error_manager initialize(wj::wjLidarParams params);// 初始化
    +Error_manager get_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, std::chrono::steady_clock::time_point command_time, int timeout_milli=1500);// 外部调用获取点云
    +bool get_connection_status();// 获取连接状态
    +bool get_initialize_status();// 获取初始化情况
    -std::thread* m_client_thread; // 异步读取线程
    -Async_Client* mp_client; // 异步客户端句柄
    -Wj_716_lidar_protocol*  mp_protocol; // 万集雷达协议句柄
}

class wj_lidar_task
{
    +virtual Error_manager init(); // 父类继承，初始化函数
    +Wj_lidar_Task();// 构造函数
    +~Wj_lidar_Task();// 析构
    +Error_manager get_command(wj_command &command);// 获取命令
    +Error_manager set_command(wj_command command);// 设置测量命令
    +Error_manager set_result(wj_measure_result result);// 将测量结果存入该任务单
    +Error_manager get_result(wj_measure_result &result);// 将测量结果传出
    +bool get_result_flag();// 获取测量结果是否已存入该任务单的指标
}

class Task_Base
{
    +~Task_Base();
    +virtual Error_manager init();//初始化任务单,初始任务单类型为 UNKONW_TASK
    +Error_manager update_statu(Task_statu task_statu,std::string statu_information="");//更新任务单
    +Task_type   get_task_type();//获取任务类型
    +Task_statu  get_statu();//获取任务单状态
    +std::string get_statu_information();//获取状态说明
}

class plc_data << (S,#FF7700) Singleton >>
{   
    +static Plc_data *get_instance(std::string ip = "");// 获取plc通信类单例
    +void update_data(int state_code, int border_status, int id);// 更新区域状态数据
    +static void plc_update_thread(Plc_data *p);// plc更新线程
    +bool get_plc_status();// 获取plc实时状态
    -std::thread *mp_update_thread; // plc更新线程
    -S7PLC m_plc; // S7协议句柄
}

class region_detect
{
    +Region_detector(int id, wj::Region region);// 有参构造函数
    +~Region_detector();// 析构函数
    +Error_manager detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in);// 检测传入点云是否为合法四轮
    +Error_manager detect(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, double &x, double &y, double &c, double &wheelbase, double &width, bool print=true);// 检测传入点云，识别为四类返回中心点、角度、轮距与宽度
    +int get_region_id();// 获得区域id
    -wj::Region m_region_param; // 区域范围参数
    -std::atomic<int> m_region_id; // 区域id
}

class region_worker
{
    +Region_worker(int id, wj::Region region, Verify_result* verify_handle);// 有参构造
    +~Region_worker();// 析构函数
    +void update_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in);// 外部调用传入新点云
    +static void detect_loop(Region_worker *worker);// 实时检测线程函数
    +int get_id();// 获取区域id
    +Error_manager get_wheel_result(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, double &x, double &y, double &c, double &wheelbase, double &width);// 获得中心点、角度等测量数据
    -std::thread *m_detect_thread; // 实时检测线程
    -Region_detector *m_detector; // 区域检测算法实例
}

note left of fence_controller
    ×电子围栏主类，包括各雷达指针、区域指针以及plc指针
    ×三个线程，更新线程负责获取各雷达点云，拼接并更新至各区域
    ×轮距任务监听线程负责监听从nnxx获取的对特定终端区域计算任务，计算完成后的结果由发送线程以nnxx中间件发送
    ×上述轮距计算任务也可以由主程序调用execute_task函数完成
end note

class fence_controller
{ 
    +Fence_controller(Verify_result* verify_handle);// 有参构造函数
    +~Fence_controller();// 析构函数
    +Error_manager initialize(wj::wjManagerParams params);// 初始化函数
    +Error_manager get_current_status();// 获取当前整体状态函数
    +Error_manager get_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out);// 外部获取点云
    +bool get_initialize_status();// 获取初始化状态
    +Error_manager execute_task(Task_Base* task);// 接收任务单进行阻塞式处理
    -std::vector<Wj_lidar_encapsulation *> m_lidars_vector; // 万集雷达实例指针数组
    -std::vector<Region_worker *> m_region_workers_vector;  // 区域功能实例指针数组
    -Plc_data *mp_plc_data; // plc句柄
    -std::thread *m_update_thread; // 更新线程
    -std::thread *m_wheel_recv_thread;      // 轮距计算任务监听线程
    -std::thread *m_wheel_send_thread;      // 轮距计算结果发送线程
    -threadsafe_queue<MsgTask> m_msg_queue; // 轮距计算任务队列
}

class globalmsg << (M,#00FF77) message>>
{

}

class wj_lidar_msg << (M,#00FF77) message>>
{

}

class wj_lidar_conf << (M,#00FF77) message>>
{

}

Task_Base <|-- wj_lidar_task
wj_lidar_encapsulation <-- wj_716_lidar_protocol
wj_lidar_encapsulation <-- async_client
wj_716_lidar_protocol <-- wj_lidar_conf
region_detect <-- wj_lidar_conf
region_worker <-- region_detect
fence_controller <-- plc_data
fence_controller <-- wj_lidar_encapsulation
fence_controller <-- region_worker
fence_controller <-- wj_lidar_task
fence_controller <-- globalmsg
plc_data <-- wj_lidar_msg
@enduml