@startuml

title PLC模块

note top of CLibmodbusWrapper
    ×PLC底层封装类，非线程安全
end note

class CLibmodbusWrapper
{
    +CLibmodbusWrapper();
    +virtual ~CLibmodbusWrapper();
    +int initialize(const char *ip, int port, int slave_id);
    +void deinitialize();
    +int read_registers(int addr, int nb, uint16_t *dest);
    +int write_registers(int addr, int nb, uint16_t *dest);
    +int read_register(int addr, uint16_t *dest);
    +int write_register(int addr, uint16_t *dest);
    +inline bool is_connected() { return (0 == _ctx) ? false : true; };
    +inline std::string getIP() { return _ip; };
    +inline int getPort() { return _port; };
    +inline int getSlave() { return _slave_id; };

    -modbus_t* _ctx;
    -std::string _ip;
    -int _port;
    -int _slave_id;
}

note right of Plc_Communicator
    ×PLC通信类，核心模块，线程安全，包括:
    ×根据plc信号调用回调进行测量
    *将测量系统实时状态与测量结果写入plc
end note

class Plc_Communicator
{
    +Plc_Communicator(plc_module::plc_connection_params connection_params);
    +~Plc_Communicator();
    +bool get_initialize_status();// 获取初始化状态
    +bool get_connection();// 获取连接状态
    +Error_manager get_error();// 获取历史错误信息
    +Error_manager set_plc_callback(Command_Callback callback, void * p_owner);// 设置plc检测到指令后外部回调函数
    +Error_manager execute_task(Task_Base* task);// 执行任务单
    +Error_manager get_plc_data(std::vector<uint16_t> &plc_data,int terminal_id=-1);// 获取实时数据
    +Error_manager set_status_update_timeout(int millisecond);// 设置plc状态更新超时时间
    +struct plc_region_status // 包含时间戳、指令信息、实时状态
    {
        std::chrono::steady_clock::time_point last_time_point;
        int current_status;
        int cmd;
    };
    -Error_manager ReadProtoParam(std::string path);// 读配置函数
    -static void plc_update_thread(Plc_Communicator* plc_communicator);// 读PLC各雷达模块信息线程函数
    -static void plc_publish_message(Plc_Communicator* plc);// 发布读取结果到UI线程函数
    -Error_manager write_result_to_plc(struct measure_result result);// 写测量数据到PLC函数
    -Error_manager connect();// 连接函数
    -Error_manager disconnect();// 断开连接

    -bool mb_plc_is_connected;// 指示plc连接状态
    -bool mb_plc_initialized; // 指示plc是否初始化
    -bool mb_plc_is_updating; // 指示plc线程在运行
    -void* mp_plc_owner;  // 回调函数所有者句柄
    -Command_Callback    m_plc_callback; // 回调函数
    -std::thread*   m_plc_message_thread; // plc
    -std::thread*   m_plc_thread; // plc更新线程句柄
    -StdCondition   m_plc_cond_exit; // plc更新线程退出条件控制变量
    -std::mutexm_plc_mutex; // plc更新互斥锁，锁住与wrapper相关的所有操作
    -modbus::CLibmodbusWrapper  m_plc_wrapper; // plc连接与读写封装实例
    -std::string    m_plc_ip_str;// plc连接ip
    -int  m_plc_port; // plc连接端口
    -int  m_plc_slave_id; // plc连接id
    -int  m_plc_status_update_timeout; // plc状态更新超时时间
    -std::vector<uint16_t>   m_plc_data; // 从plc获取的实时数据
    -Error_manager       m_plc_current_error; // 当前plc出现的错误
    // 当前系统状态，实时更新到plc。状态254-255每1秒互换，状态1从收到指令开始，紧接着改为状态2，
    // 之后根据外部传入的task，决定写入3或4，默认3保留3秒，4持续保留直到新指令
    -plc_region_status   m_plc_region_status[PLC_REGION_NUM];
}

class plc_message::plcMsg << (M,#00FF77) message>>
{
    plcStatus plc_status=1;
    int32 plc_values=2;
}

class plc_module::plc_connection_params << (M,#00FF77) message>>
{
    string ip=1;
    int32 port=2;
    int32 slave_id=3;
}

class plc_module::Plc_msg << (M,#00FF77) message>>
{
    PLC_STATUS status=1;
    int32 plc_values=2;
}

class Plc_Task
{
    +virtual Error_manager init(); 
    +Plc_Task();
    +~Plc_Task();
    +Error_manager set_result(struct measure_result result);// 将测量结果存入该任务单
    +Error_manager get_result(struct measure_result &result);// 将测量结果传出
    +bool get_result_set_flag();// 获取测量结果是否已存入该任务单的指标

    -struct measure_result m_measure_result;// 存放测量结果
    -bool mb_result_set_flag;// 已获取结果
    -struct measure_result
    {
        int terminal_id;
        float x;
        float y;
        float angle;
        float length;
        float width;
        float height;
        float wheel_base;
        bool correctness;
    };
}

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

Task_Base <|-- Plc_Task
Plc_Communicator <-- Plc_Task
Plc_Communicator <-- plc_message::plcMsg
Plc_Communicator <-- plc_module::plc_connection_params
Plc_Communicator <-- plc_module::Plc_msg
Plc_Communicator <-- CLibmodbusWrapper

@enduml