// // Created by huli on 2020/9/25. // #include "snap7_communication_base.h" #include "../tool/proto_tool.h" Snap7_communication_base::Snap7_communication_base() { m_communication_status = SNAP7_COMMUNICATION_UNKNOWN; m_communication_delay_time_ms = SNAP7_COMMUNICATION_DELAY_TIME_MS; mp_communication_thread = NULL; } Snap7_communication_base::~Snap7_communication_base() { communication_uninit(); } //初始化 通信 模块。如下三选一 Error_manager Snap7_communication_base::communication_init(std::string ip) { m_ip_string=ip; Error_manager t_error = communication_connect(m_ip_string); if ( t_error != Error_code::SUCCESS ) { //连接失败, 不要直接返回, 而是改为断连, 后面继续启动线程, (线程内部有重连功能) m_communication_status = SNAP7_COMMUNICATION_DISCONNECT; return t_error; } else { m_communication_status = SNAP7_COMMUNICATION_READY; } return communication_run(); } //反初始化 通信 模块。 Error_manager Snap7_communication_base::communication_uninit() { //关闭线程并回收资源 if (mp_communication_thread) { m_communication_condition.kill_all(); } if (mp_communication_thread) { mp_communication_thread->join(); delete mp_communication_thread; mp_communication_thread = NULL; } //清空map { std::unique_lock t_lock(m_receive_buf_lock); m_receive_buf_map.clear(); } { std::unique_lock t_lock(m_send_buf_lock); m_send_buf_map.clear(); } communication_disconnect(); m_communication_status = SNAP7_COMMUNICATION_UNKNOWN; return Error_code::SUCCESS; } //唤醒s7通信线程 Error_manager Snap7_communication_base::communication_start() { m_communication_condition.notify_all(true); return Error_code::SUCCESS; } //停止s7通信线程 Error_manager Snap7_communication_base::communication_stop() { m_communication_condition.notify_all(false); return Error_code::SUCCESS; } Snap7_communication_base::Snap7_communication_statu Snap7_communication_base::get_status() { return m_communication_status; } //通信连接 Error_manager Snap7_communication_base::communication_connect(std::string ip_string) { std::unique_lock t_lock(m_communication_lock); int result=m_snap7_client.ConnectTo(ip_string.c_str(),0,1); std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms)); if (result==0) { return Error_code::SUCCESS; } else { return Error_manager(Error_code::SNAP7_CONNECT_ERROR, Error_level::MINOR_ERROR, " Snap7_communication_base::communication_connect error "); } return Error_code::SUCCESS; } //启动通信, run thread Error_manager Snap7_communication_base::communication_run() { //启动4个线程。 //接受线程默认循环, 内部的nn_recv进行等待, 超时1ms m_communication_condition.reset(false, false, false); mp_communication_thread = new std::thread(&Snap7_communication_base::communication_thread, this); return Error_code::SUCCESS; } //通信断连 Error_manager Snap7_communication_base::communication_disconnect() { std::unique_lock t_lock(m_communication_lock); int result=m_snap7_client.Disconnect(); std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms)); if (result==0) { return Error_code::SUCCESS; } else { return Error_manager(Error_code::SNAP7_DISCONNECT_ERROR, Error_level::MINOR_ERROR, " Snap7_communication_base::communication_disconnect error "); } return Error_code::SUCCESS; } //mp_communication_thread线程的执行函数, 负责进行s7的通信 void Snap7_communication_base::communication_thread() { //LOG(INFO) << " ---Snap7_communication_base::communication_thread()--- "<< this; Error_manager t_error; while (m_communication_condition.is_alive()) { m_communication_condition.wait_for_millisecond(1); //s7的通信时间较长, 所以将发送和接受分开 //发送多个时, 必须加锁后一起发送, 不允许分段写入, 防止数据错误 if ( m_communication_condition.is_alive() ) { std::this_thread::sleep_for(std::chrono::milliseconds(m_communication_delay_time_ms)); std::this_thread::yield(); switch ( m_communication_status ) { case SNAP7_COMMUNICATION_READY: case SNAP7_COMMUNICATION_RECEIVE: { { std::unique_lock t_lock(m_receive_buf_lock); auto iter = m_receive_buf_map.begin(); for (; iter != m_receive_buf_map.end(); ++iter) { //接受数据, 读取DB块, t_error = read_data_buf(iter->second); if (t_error == Error_code::SNAP7_READ_ERROR) { m_communication_status = SNAP7_COMMUNICATION_DISCONNECT; std::cout << " huli test :::: " << " t_error = " << t_error << std::endl; break; } } if ( iter != m_receive_buf_map.end() ) { break; } } //注:数据更新放在锁的外面, 防止重复加锁.... updata_receive_buf(); m_communication_status = SNAP7_COMMUNICATION_SEND; break; } case SNAP7_COMMUNICATION_SEND: { //注:数据更新放在锁的外面, 防止重复加锁.... updata_send_buf(); { std::unique_lock t_lock(m_send_buf_lock); auto iter = m_send_buf_map.begin(); for (; iter != m_send_buf_map.end(); ++iter) { //发送数据, 写入DB块, t_error = write_data_buf(iter->second); if (t_error == Error_code::SNAP7_WRITE_ERROR) { m_communication_status = SNAP7_COMMUNICATION_DISCONNECT; std::cout << " huli test :::: " << " t_error = " << t_error << std::endl; break; } } if ( iter != m_send_buf_map.end() ) { break; } } m_communication_status = SNAP7_COMMUNICATION_RECEIVE; break; } case SNAP7_COMMUNICATION_DISCONNECT: { //重连 std::cout << "find plc connection error, trying to reconnect."< lck(m_communication_lock); int result = m_snap7_client.AsDBRead(snap7_buf.m_id, snap7_buf.m_start_index, snap7_buf.m_size, snap7_buf.mp_buf_reverse); // std::this_thread::sleep_for(std::chrono::milliseconds(10)); if ( result == 0 ) { m_snap7_client.WaitAsCompletion(100); //倒序数据 转为 正序数据 //snap7_buf.reverse_to_obverse(); } else { std::cout << " huli test :::: " << " result = " << result << std::endl; return Error_manager(Error_code::SNAP7_READ_ERROR, Error_level::MINOR_ERROR, " Snap7_communication_base::read_data_buf error "); } } return Error_code::SUCCESS; } //发送数据, 写入DB块, Error_manager Snap7_communication_base::write_data_buf(Snap7_buf& snap7_buf) { Error_manager t_error; if ( snap7_buf.m_communication_mode != Snap7_buf::NO_COMMUNICATION) { if ( snap7_buf.m_communication_mode == Snap7_buf::ONCE_COMMUNICATION ) { snap7_buf.m_communication_mode = Snap7_buf::NO_COMMUNICATION; } //正序数据 转为 倒序数据 //snap7_buf.obverse_to_reverse(); std::unique_lock lck(m_communication_lock); unsigned short a=0; memcpy(&a,snap7_buf.mp_buf_reverse,2); //printf("id %d start %d size :%d value :%d\n",snap7_buf.m_id, snap7_buf.m_start_index, snap7_buf.m_size,a); int result = m_snap7_client.AsDBWrite(snap7_buf.m_id, snap7_buf.m_start_index, snap7_buf.m_size, snap7_buf.mp_buf_reverse); // std::this_thread::sleep_for(std::chrono::milliseconds(10)); if ( result == 0 ) { if(0!=m_snap7_client.WaitAsCompletion(100)) { return Error_manager(Error_code::SNAP7_WRITE_ERROR, Error_level::MINOR_ERROR, " Snap7_communication_base::write_data_buf error "); } } else { return Error_manager(Error_code::SNAP7_WRITE_ERROR, Error_level::MINOR_ERROR, " Snap7_communication_base::write_data_buf error "); } } return Error_code::SUCCESS; } //数据颠倒 Error_manager Snap7_communication_base::reverse_byte(void* p_buf_in, void* p_buf_out, int size) { if ( p_buf_in == NULL || p_buf_out == NULL ) { return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR, " POINTER IS NULL "); } char* tp_in=(char*)p_buf_in; char* tp_out=(char*)p_buf_out; // for(int i=0;i