Eip开源主站EIPScanner在Linux上的调试记录(二 多生产者连接)

发布于:2025-09-16 ⋅ 阅读:(19) ⋅ 点赞:(0)

目录

一、背景

二、可行性验证

三、开发调试


一、背景

在一般场景下,只需一路IO连接,但稍微复杂的场景,就需要不同通讯周期的连接,这就需要有多组IO连接。

而大于一组的连接调试方法是一样的,因此主要解决2组连接的代码开发。

二、可行性验证

在Eip Scanner Demo(主站)、PLC(从站)软件上分别配置两个生产者连接,验证其数据收发可行性及稳定性。得到视频及报文如下:

1、Enip

2、ForwardOpen 1

3、ForwardOpen 2

4、ForwardCloes 2

5、ForwardCloes 1

可见,进行了两次ForwardOpen,建立了两个生产者连接。

由上文可见,两个生产者连接的ForwardOpen的不同点在于:

1、Connection Path 由PLC自动生成,直接配置到Ubuntu中

2、Connecte Serial Number 自由选择,只要是两个连接不同即可,见协议原文

3、Connection Parameter (可选,如果两个收发字节数相同,则此项也相同)

因此,便可满足上述要求情况下,将多生产者连接集成到一个SDK中。

但需要注意多线程下的单一物理网口的数据抢占问题。

三、开发调试

发现在_connectionMap中管理了所有的IO连接。

在forwardopen阶段注册_connectionMap,每开一个IO连接都会注册一个_connectionMap进去

在handleConnections中,若IO连接不存在,则删除掉

而在代码中,无需在两个连接的情况下守护两个connectionManager,于是更改代码如下:

int main() {
 。。。。
 

  parameters.o2tRealTimeFormat = true;
  parameters.t2oRealTimeFormat = true;
  parameters.originatorVendorId = 0xaa;
  parameters.connectionTimeoutMultiplier=2;
  parameters.priorityTimeTick=10;
  parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
  parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
  parameters.t2oNetworkConnectionParams |= 0; //size of Assm100 =1
  parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
  parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
  parameters.o2tNetworkConnectionParams |= 4; //size of Assm100 =1
  parameters.originatorSerialNumber = 0x012345;

  parameters.o2tRPI = 50000;
  parameters.t2oRPI = 50000;//50ms
  parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;
  parameters.transportTypeTrigger |= NetworkConnectionParams::TRIG_CYCLIC;  
  std::chrono::milliseconds timeout(5000);
//connect one
  auto si_1 = std::make_shared<SessionInfo>("192.168.2.88", 0xAF12,timeout,50000);
  ConnectionManager connectionManager_1;
  parameters.connectionPath = {0x20, 0x04,0x24, 0x01, 0x2C, 0x65, 0x2C, 0xFF}; 
  parameters.connectionSerialNumber = 0xbebc;
  auto io_1 = connectionManager_1.forwardOpen(si_1, parameters);
  if (auto ptr = io_1.lock()) {
    ptr->setDataToSend(std::vector<uint8_t>(4));

    ptr->setReceiveDataListener([](auto realTimeHeader, auto sequence, auto data) {
      std::ostringstream ss;
      ss << "secNum=" << sequence << " data=";
      for (auto &byte : data) {
        ss << "[" << std::hex << (int) byte << "]";
      }

      Logger(LogLevel::INFO) << "Received: " << ss.str();
    });

    ptr->setCloseListener([]() {
      Logger(LogLevel::INFO) << "Closed";
    });
  }

//connect two
  auto si_2 = std::make_shared<SessionInfo>("192.168.2.88", 0xAF12,timeout,50050);
  //ConnectionManager connectionManager_2;

  parameters.connectionPath = {0x20, 0x04,0x24, 0x01, 0x2C, 0x64, 0x2C, 0x6E}; 
  parameters.connectionSerialNumber = 0x275D;
  //auto io_2 = connectionManager_2.forwardOpen(si_2, parameters);
    auto io_2 = connectionManager_1.forwardOpen(si_2, parameters);
  if (auto ptr = io_2.lock()) {
    ptr->setDataToSend(std::vector<uint8_t>(4));

    ptr->setReceiveDataListener([](auto realTimeHeader, auto sequence, auto data) {
      std::ostringstream ss;
      ss << "secNum=" << sequence << " data=";
      for (auto &byte : data) {
        ss << "[" << std::hex << (int) byte << "]";
      }

      Logger(LogLevel::INFO) << "Received: " << ss.str();
    });

    ptr->setCloseListener([]() {
      Logger(LogLevel::INFO) << "Closed";
    });
  }

//handle connect
  while (connectionManager_1.hasOpenConnections()) {
    connectionManager_1.handleConnections(std::chrono::milliseconds(50));
   // connectionManager_2.handleConnections(std::chrono::milliseconds(50));
  }
    connectionManager_1.forwardClose(si_1, io_1);
    connectionManager_1.forwardClose(si_2, io_2);

。。。。

  return EXIT_SUCCESS;
}

显示Log如下,能正常维持两个连接

wireshark报文如下:

此系列的b站视频见:

基于EIPScanner的Linux Ethernet/IP的多生产者连接及Tag读写实现分享(一 引言)_哔哩哔哩_bilibili

参考代码见:

咸鱼ID:tb764914262


网站公告

今日签到

点亮在社区的每一天
去签到