nimbuscontrols / eipscanner Goto Github PK
View Code? Open in Web Editor NEWFree implementation of EtherNet/IP in C++
Home Page: https://eipscanner.readthedocs.io/en/latest/
License: MIT License
Free implementation of EtherNet/IP in C++
Home Page: https://eipscanner.readthedocs.io/en/latest/
License: MIT License
4
Is there any plan to support VS compilation?
An idea to add a default styling "something, e.g. AStyle" to the project to keep formatting aligned?
Hi all,
I am currently working on a project that involves the usage of am64x evm as an ethernet/ip adapter. In order to test out this functionality, I have been looking for ethernet/ip scanner (master) running on PC. Can anyone tell me if the EIP Scanner will serve this purpose?
I am planning to use my laptop (running EIP scanner) as the ethernet/ip master and am64x as ethernet/ip slave. Can anyone tell me if this is possible. I am new to this field , any type of help will be appreciated.
Thank you.
Scaling attributes were incorrect in multithreaded program because of uninitialized variables in the ParameterObject constructor
We need to implement DiscoveryManager class, which has a method to send broadcasting requests via UDP. The method receives the UDP responses and returns a vector of structures. The structure will contain IdentyObject and information about IP and port. Each structure describes one device in the network.
I am trying to use EIPScanner to connect AB 1794 IO. It seems the IO module only can be connected through adapter module's proxy connect. I got the connection path of " 01 00 20 04 24 03 2C 04 2C 02", but after set this value in EIPScanner, it always reports "Message router error=0x1 additional statuses [0x109].
I want to know if EIPScanner support proxy connect?
Thanks,
David
How do I use it
NetworkConnectionParametersBuilder
/*"+================================================================
*/
NetworkConnectionParametersBuilder ParametersBuilder;
// CipUint(ParametersBuilder.getConnectionSize())
Logger(LogLevel::INFO) << CipUint(ParametersBuilder.getConnectionSize());
/*"+================================================================
Thank you for sharing this library, and this is a question first of all and not a bug, but there is no other place to ask.
I have a simple question: Is it possible by using this library to read/write directly the I/O ports of a device(sensor, robot etc.) over simple laptop network card (without using any specific hardware-- for example Hilscher CifX Re50 card)?
The project must be documented:
7
I have 2 EthernetIP devices (both TURCK models) with 2 distinct IP addresses. I am able to talk to each of them separately and set bits. But when I try to talk to both of them in the same program, it does not work.
Here is the Connection1 details from the EDS file:
$
[Connection Manager]
Connection1 =
0x04010002, $ 0-15 = supported transport classes
$ --------------------------------------
$ @16 = trigger: cyclic
$ 17 = trigger: change of state
$ 18 = trigger: application
$ 19 = trigger: reserved
$ --------------------------------------
$ 20-23 = trigger: reserved
$ --------------------------------------
$ 24 = transport type: listen-only
$ 25 = transport type: input-only
$ @26 = transport type: exclusive-owner
$ 27 = transport type: redundant-owner
$ --------------------------------------
$ 28-30 = reserved
$ 31 = Client = 0 / Server = 1
$ --------------------------------------
0x44640405, $ @0 = O->T fixed size supported
$ 1 = O->T variable size supported
$ @2 = T->O fixed size supported
$ 3 = T->O variable size supported
$ ---------------------------------------
$ 4-5 = O->T number of bytes per slot (obsolete)
$ 6-7 = T->O number of bytes per slot (obsolete)
$ ---------------------------------------
$ 8-10 = O->T Real time transfer format
$ 11 = reserved
$ --------------------------------------
$ 12-14 = T->O Real time transfer format
$ 15 = reserved
$ --------------------------------------
$ 16 = O->T connection type: NULL
$ 17 = O->T connection type: MULTICAST
$ @18 = O->T connection type: POINT2POINT
$ 19 = O->T connection type: reserved
$ --------------------------------------
$ 20 = T->O connection type: NULL
$ @21 = T->O connection type: MULTICAST
$ @22 = T->O connection type: POINT2POINT
$ 23 = T->O connection type: reserved
$ --------------------------------------
$ 24 = O->T priority: LOW
$ 25 = O->T priority: HIGH
$ @26 = O->T priority: SCHEDULED
$ 27 = O->T priority: reserved
$ --------------------------------------
$ 28 = T->O priority: LOW
$ 29 = T->O priority: HIGH
$ @30 = T->O priority: SCHEDULED
$ 31 = T->O priority: reserved
$ --------------------------------------
,,Assem104, $ O->T RPI, size in bytes, format
,,Assem103, $ T->O RPI, size in bytes, format
,, $ config #1 size in bytes, format
,Assem106, $ config #2 size in bytes, format
"Exclusive Owner", $ Connection Name
"", $ Fixed data size, input inst. 103, output inst. 104
"20 04 24 6A 2C 68 2C 67"; $ Path
Here are the settings that I modified within ImplicitMessagingExample.cpp:
parameters.connectionPath = {0x20, 0x04, 0x24, 0x6A, 0x2C, 0x68, 0x2C, 0x67};
parameters.o2tRealTimeFormat = true;
parameters.originatorVendorId = 501; // VendCode from VIPA EDS.
parameters.originatorSerialNumber = 5038;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.t2oNetworkConnectionParams |= 10;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.o2tNetworkConnectionParams |= 10;
parameters.o2tRPI = 1000000;
parameters.t2oRPI = 1000000;
parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;
I modified the ImplictMessagingExample.cpp by wrapping the initialization, open, close, set and get bits into a class and associated functions.
Example:
eipWrapper::EIPWrapper wrapper1("192.168.1.111");
wrapper1.open();
std::this_thread::sleep_for (std::chrono::seconds(3));
eipWrapper::EIPWrapper wrapper2("192.168.1.112");
wrapper2.open();
This does not throw any errors. Output:
[INFO] Registered session 102
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Connection state: 0
[INFO] Open IO connection O2T_ID=3494509568 T2O_ID=224198657 SerialNumber 1
[INFO] Open UDP socket to send data to 192.168.1.111:2222
*****
[INFO] Registered session 102
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Connection state: 0
[INFO] Open IO connection O2T_ID=3495502080 T2O_ID=224198658 SerialNumber 2
[INFO] Open UDP socket to send data to 192.168.1.112:2222
*****
[INFO] Close connection connection T2O_ID=224198657
[INFO] Send request: service=0x4e epath=[classId=6 objectId=1]
[INFO] Close connection connection T2O_ID=224198658
[INFO] Send request: service=0x4e epath=[classId=6 objectId=1]
[INFO] Unregistered session 102
[INFO] Unregistered session 102
However, when I try to set the 0th bit for one of the devices.
[INFO] Registered session 102
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Connection state: 0
[INFO] Open IO connection O2T_ID=3530795776 T2O_ID=779026433 SerialNumber 1
[INFO] Open UDP socket to send data to 192.168.1.111:2222
*****
[INFO] Registered session 102
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Connection state: 0
[INFO] Open IO connection O2T_ID=3531788800 T2O_ID=779026434 SerialNumber 2
[INFO] Open UDP socket to send data to 192.168.1.112:2222
*****
[INFO] Received: secNum=2 data=[0][0][0][0][0][0][0][0][0][0]
[INFO] Received: secNum=3 data=[0][0][0][0][0][0][0][0][0][0]
[INFO] Received: secNum=4 data=[0][0][0][0][0][0][0][0][0][0]
[ERROR] Received data from unknown connection T2O_ID=779026434
[WARNING] Connection O2T_ID=3530795776 has fixed size 10 bytes but 0 bytes are to send. Don't send this data.
[INFO] Current bytes before: [0][0][0][0][0][0][0][0][0][0]
[INFO] Current bytes after: [0][0][1][0][0][0][0][0][0][0]
[INFO] data size: 10
[WARNING] Connection SeriaNumber=1 is closed by timeout4100000:4000000
[INFO] Closed
[WARNING] Attempt to close an already closed connection
[INFO] Close connection connection T2O_ID=779026434
[INFO] Send request: service=0x4e epath=[classId=6 objectId=1]
[INFO] Unregistered session 102
[INFO] Unregistered session 102
I tried to launch each device in its own process. I had a bit toggle every second for a second. The moment the second device received the bit, I see this on the first one's log:
[DEBUG] Received data from connection T2O_ID=1703018497
[INFO] Received: secNum=1 data=[0][0][0][0][0][0][0][0][0][0]
[WARNING] Connection SeriaNumber=1 is closed by timeout4099000:4000000
[INFO] Closed
[DEBUG] Close socket fd=4
And the first one stops responding.
Expected behavior
I expect the library to be able to set the bits on each of the devices independently.
Environment (please complete the following information):
3
5
Describe the bug
After a find_package
in my project noticed that the EIPScanner_INCLUDE_DIRS
is not defined.
To Reproduce
Build the package, include it in another project.
Expected behavior
A location to the include directory.
Environment (please complete the following information):
Additional context
find_library(EIPScanner_LIB EIPScanner)
does work.
Hi,
I installed EIPScanner. Now I'm trying to run the example cited here on my Raspberry Pi 3. After running "cmake .." I don't see no executable files. So, I cannot run "./hi_eip". Any help would be highly welcome! Thank you very much in advance.
PS: I am quite new to using CMake.
EDIT:
The command in order to build the CMake files "cmake --build ." was missing. I could manage to create the executable file. But now I have the error: "error while loading shared libraries: libEIPScanner.so.1: cannot open shred object file: No such file or directory". Any idea how I can solve this?
Kindly regards
Gaetan
Apologies for marking this as a bug, it should probably be a 'question', but Git doesn't want to let me switch the labels
I'm new to EIP and I'm trying to open an implicit messaging loop with a Siemens drive device using this eds. I thought I understood things, but when I tried to establish the connection using my understanding of the parameters, I got a 0x13 "not enough data supplied" error from the stack. Thought that was a little strange so I opened up the ImplicitMessagingExample and updated the path with the one on line 371 of that file, or-equaled the t2o network connection parameters to indicate multicast support, and switched the IP address for the one our device is using (and confirmed via ping). Unfortunately, even the example code (with my updates) is returning a 0x13 error.
I don't understand what's going on here...am I missing a nuance in how EIP is supposed to work? Is the stack incompatible with Siemens devices? Do I just need to update some other parameters because something is being finicky under the hood?
Can you shed some light on any of this?
Thanks!
Refer to CIP Vol1 (3.24) - 5A-42.2
Class code: 0x37
Attribute ID: 32
Instance ID: 0 (base class)
Access rule: Get
Name: Directory
Data type: Array of: Struct of:
Also requires implementation of STRINGI:
Already have this working but in a quick and dirty way. Will work it neatly into the library later. At least will add the structure but if wanted I could also add e.g. a functionality to retrieve a list of files from a device.
Describe the bug
I can open an implicit connection with the device and it is working for a while, but then it is closed by timeout after 10 messages have been received.
To Reproduce
I use the following code:
auto si = std::make_shared<SessionInfo>("172.28.1.3", 0xAF12); // Here I have an exception!!
ConnectionManager connectionManager(messageRouter);
ConnectionParameters parameters;
parameters.connectionPath = {0x20, 0x04,0x24, 6, 0x2C, 2, 0x2C, 1};
parameters.o2tRealTimeFormat = true;
parameters.originatorVendorId = 342;
parameters.originatorSerialNumber = 32423;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.t2oNetworkConnectionParams |=12
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.o2tNetworkConnectionParams |= 12
parameters.o2tRPI = 1000000;
parameters.t2oRPI = 1000000;
parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;
auto io = connectionManager.forwardOpen(si, parameters);
if (auto ptr = io.lock()) {
ptr->setDataToSend(std::vector<uint8_t>(32));
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";
});
}
int count = 200;
while (connectionManager.hasOpenConnections() && count-- > 0) {
connectionManager.handleConnections(std::chrono::milliseconds(100));
}
connectionManager.forwardClose(si, io);
return 0;
Expected behavior
I must have received 20 messages instead of 10.
Wireshark dump
wrong_communication_with_eipscanner.zip
good_communication_with_other_lib.zip
Logs
[DEBUG] Opened socket fd=3
[DEBUG] Parsing IP from 192.168.1.15
[DEBUG] Connecting to 192.168.1.15:44818
[INFO] Registered session 12
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Open IO connection O2T_ID=1489698821 T2O_ID=1 SerialNumber 1
[DEBUG] Opened socket fd=4
[DEBUG] Parsing IP from 192.168.1.15
[DEBUG] Opened socket fd=5
[DEBUG] Parsing IP from 192.168.1.15
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=1 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=2 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=3 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=4 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=5 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=6 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=7 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=8 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=9 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[DEBUG] Received data from connection T2O_ID=1
[INFO] Received: secNum=10 data=[0][0][0][0][8c][0][0][0][0][0][0][0]
[WARNING] Connection SeriaNumber=1 is closed by timeout
[INFO] Closed
[DEBUG] Close socket fd=4
[WARNING] Attempt to close an already closed connection
[DEBUG] Close socket fd=5
[INFO] Unregistered session 12
[DEBUG] Close socket fd=3
Process finished with exit code 0
Environment (please complete the following information):
6
Hi
I'm using the "reset" (0x05) service of the "identity" (0x01) class to bring my device into a defined state.
In my current implementation has to handle an exception because - I think - the "SessionInfo" destructor sends a "sign off" package to the now defunc session.
Is there a better way to use the reset service?
Thanks Mario
Will someone with a windows computer test one of the examples from this fork #39 by @luntik2012 compiling with mingw, so I can merge this pull request and create release 1.1.0 that allows for windows support?
Thanks
I am writing an EIP Scanner for the bluebotics ANT lite+. My CMake project needs to depend on this library, but I can't figure out how to set that up. Why can I not find the package after building and installing it?
Hi, everyone,
first of all, thank you for sharing this library and sorry for putting this issue as a bug, it is question (or a cry for help). ;-)
I am trying to use the library to communicate via implicit messages with a MUR Cube67 device. My starting point was the implicit message example. The first issue I head was to proper set the parameters, but then I found in one issue how to use 8 bits path and it worked well. So the forward open command was successful, but I don't get any UDP messages from the device. What could be the reason?
I understand that the last ENIP message is to close the connection, but I am not sure if this is really the case. This is the console output:
Here is my main.cpp file:
#include <sstream>
#include <cip/connectionManager/NetworkConnectionParams.h>
#include "SessionInfo.h"
#include "ConnectionManager.h"
#include "utils/Logger.h"
#include "utils/Buffer.h"
using namespace eipScanner::cip;
using eipScanner::SessionInfo;
using eipScanner::MessageRouter;
using eipScanner::ConnectionManager;
using eipScanner::cip::connectionManager::ConnectionParameters;
using eipScanner::cip::connectionManager::NetworkConnectionParams;
using eipScanner::utils::Buffer;
using eipScanner::utils::Logger;
using eipScanner::utils::LogLevel;
const uint16_t t2oSize = 52;
const uint16_t o2tSize = 10;
int main() {
Logger::setLogLevel(LogLevel::DEBUG);
auto si = std::make_shared<SessionInfo>("10.254.0.31", 0xAF12);
// Implicit messaging
ConnectionManager connectionManager;
ConnectionParameters parameters;
parameters.priorityTimeTick = 3;
parameters.timeoutTicks = 250;
parameters.connectionTimeoutMultiplier = 1;
parameters.connectionPath = {0x20, 0x04, 0x24, 0x80, 0x2C, 0x70, 0x2C, 0x64}; //
parameters.o2tRealTimeFormat = true;
parameters.originatorVendorId = 505;
parameters.originatorSerialNumber = 0x1234;
// parameters.t2oNetworkConnectionParams = NetworkConnectionParams::REDUNDANT;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.t2oNetworkConnectionParams |= t2oSize; //size of Assm100 =32
parameters.o2tRPI = 10000; //us
// parameters.o2tNetworkConnectionParams = NetworkConnectionParams::REDUNDANT;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.o2tNetworkConnectionParams |= o2tSize; //size of Assm150 = 32
parameters.t2oRPI = 10000; //us
parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;
parameters.transportTypeTrigger |= NetworkConnectionParams::TRIG_CYCLIC;
auto io = connectionManager.forwardOpen(si, parameters);
if (auto ptr = io.lock()) {
ptr->setDataToSend(std::vector<uint8_t>(o2tSize));
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";
});
}
int count = 200;
while (connectionManager.hasOpenConnections() && count-- > 0) {
connectionManager.handleConnections(std::chrono::milliseconds(5000));
}
connectionManager.forwardClose(si, io);
return EXIT_SUCCESS;
}
´´´
Can someone give me an insight how to solve this?
Thanks a lot and BR,
Tomas
Is your feature request related to a problem? Please describe.
The current implementation doesn't have timeout for TCP\IP connection. It causes very long dealys if the IP address is not available.
Describe the solution you'd like
Implement connection timeout like this: http://developerweb.net/viewtopic.php?id=3196
Hello
I am using your library and it works perfect.
I am just wondering what parameters.o2tRealTimeFormat is for.
I have a plc that only works if I put that variable to false. So no header will be send.
But I want to understand what it is for.
Regards Grayson.
Is your feature request related to a problem?
Currently, we have no information about if the parameter provides writing.
Describe the solution you'd like
Parameter Object has a descriptor attribute (ID=4) where the needed flag exists. We should read it and add a getter method.
Recently I've been tasked to communicate with Omron NX PLCs using EthernetIP explicit messages. To access data on these devices, an EPath doesn't consist of a class id, instance id or attribute id. The segments making up the EPath should be one or more ANSI Extended Symbol Segments (with ascii data encoded), and optionally logical segments with logical type member id (not attribute id).
I've noticed EIPScanner doesn't support EPath's consisting of segments other than the logical segment and the aforementioned logical types (class, instance, attribute). Do you guys have any plans on supporting more segment types in the EPath?
The device I have to control uses implicit messaging to change runtime parameters. This is a multi stage process:
I do not understand how I have to modify the ImplicitMessagingExample.cpp
example to send multiple messages. Any ideas?
Describe the bug
Running make html
in the docs directory fails for lack of a sphinx_rtd_theme file.
To Reproduce
Run make html
in the docs directory.
Example:
jallard@jallard-VB20:~/work/EIPScanner/docs$ make html
Running Sphinx v1.8.5
Configuration error:
There is a programmable error in your configuration file:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/sphinx/config.py", line 368, in eval_config_file
execfile_(filename, namespace)
File "/usr/lib/python3/dist-packages/sphinx/util/pycompat.py", line 150, in execfile_
exec_(code, _globals)
File "/home/jallard/work/EIPScanner/docs/source/conf.py", line 19, in <module>
import sphinx_rtd_theme
ModuleNotFoundError: No module named 'sphinx_rtd_theme'
make: *** [Makefile:19: html] Error 2
Expected behavior
I was hoping for some nicely formatted documentation.
Environment (please complete the following information):
Hi,
I am pretty new with the EIPScanner stack and trying to use it to communicate with Sick Gateway (more specifically FX3-GEPR00000) which then is connected to the main PLC and some other blocks. The gateway is the main linking point where all the data can be fetched from. I have a EDS file but I am not sure how to use the same here with the stack. The FileObjectExample.cpp
example in the source seems to be using some output stream for uploading eds file, but I couldn't get the idea how I can I use the provided eds file from the vendor with the stack. I tried to use the explicit/implicit example too but they fails to establish connection with an error of 'what : Resource temporarily unavailable'
I tried to dig dive more and enable the trace logs and found it actually establishes a TCP connection and then send some 24 bytes of data but does not get any reply from other side timesout and throws this error.
I am not sure the data sent here is some standard message of the TCP/IP stack but the gateway seems to not understand it.
Here's the link for the eds file, any help is appreciated.
I hope this question is not as silly as it sounds: Can the EIPScanner library be used to write the code for an Ethernet/IP Adapter?
As a Scanner can do everything an Adapter does (and more!), it makes sense we could use this library to code an Adapter, right?
If so, which is the way to go? Is there any example in this library that is almost an Adapter with the typical input/output/config assembly object configuration? The Implicit Messaging example? The Yaskawa code?
Thanks!
Hi I was wondering if you could give me a notch in the right direction to set up implicit messaging to a Universal Robots robot controller?
It does not support explicit messaging. Only Implicit messaging.
I have the following EDS file and it defines two assemblies but I'm not sure how to set up the connection and how to interpret the eds.
The implicit IO example code defines serial numbers as well, are these required?
EDS File snippets.... Also see attached complete document.
[Device]
VendCode = 1399;
VendName = "Universal Robots A/S";
ProdType = 43;
ProdTypeStr = "Generic Device";
ProdCode = 1;
MajRev = 1;
MinRev = 1;
ProdName = "Universal Robot";
Catalog = "UR";
Icon = "UR_64x64.ico";
.....
[Device Classification]
Class1 = EtherNetIP;
......
[Assembly]
Assem1 =
"Input Assembly",
"20 04 24 64 30 03",
,
0x0000,
,,
$ ROBOT
8,Param1,
8,Param2,
16,, $ pad
8,Param3,
8,Param4,
16,Param5,
.......
Assem2 =
"Output Assembly",
"20 04 24 70 30 03",
,
0x0000,
,,
$ ROBOT
8,Param501,
24,, $ pad
32,Param502,
$ Outputs
8,Param503,
........
[Connection Manager]
Connection1 =
0x04010002, $ TRIGGER AND TRANSPORT MASK
$ BIT=VAL DESCRIPTION
$ 0 = 0 (class 0:null)
$ 1 = 1 (class 1:dup. detect)
$ 2 = 0 (class 2:acknowledged)
$ 3 = 0 (class 3:verified)
$ 4 = 0 (class 4:non-block)
$ 5 = 0 (class 5:non-block, frag)
$ 6 = 0 (class 6:multicast, frag)
$ 7-15 = 0 (class :reserved)
$ 16 = 1 (trigger: cyclic)
$ 17 = 0 (trigger: cos)
$ 18 = 0 (trigger: appl)
$ 19-23 = 0 (trigger: reserved (must be zero))
$ 24 = 0 (transport type: listen-only)
$ 25 = 0 (transport type: input-only)
$ 26 = 1 (transport type: exclusive-owner)
$ 27 = 0 (transport type: redundant-owner)
$ 28-30 = 0 (reserved (must be zero))
$ 31 = 1 (client = 0 / server = 1)
0x44440405, $ CONNECTION PARAMETERS BIT ASSIGNMENTS
$ BIT=VAL DESCRIPTION
$ 0 = 1 (O=>T fixed)
$ 1 = 0 (O=>T variable)
$ 2 = 1 (T=>O fixed)
$ 3 = 0 (T=>O variable)
$ 4-7 = 0 (reserved (must be zero))
$ 8-10 = 4 (O=>T header (4 byte run/idle))
$ 11 = 0 (reserved (must be zero))
$ 12-14 = 0 (T=>O header (pure data))
$ 15 = 0 (reserved (must be zero))
$ 16 = 0 (O=>T connection type: NULL)
$ 17 = 0 (O=>T connection type: MULTI)
$ 18 = 1 (O=>T connection type: P2P)
$ 19 = 0 (O=>T connection type: RSVD)
$ 20 = 0 (T=>O connection type: NULL)
$ 21 = 1 (T=>O connection type: MULTI)
$ 22 = 0 (T=>O connection type: P2P)
$ 23 = 0 (T=>O connection type: RSVD)
$ 24 = 0 (O=>T priority: LOW)
$ 25 = 0 (O=>T priority: HIGH)
$ 26 = 1 (O=>T priority: SCHEDULED)
$ 27 = 0 (O=>T priority: RSVD)
$ 28 = 0 (T=>O priority: LOW)
$ 29 = 0 (T=>O priority: HIGH)
$ 30 = 1 (T=>O priority: SCHEDULED)
$ 31 = 0 (T=>O priority: RSVD)
Param999,,Assem2, $ O=>T RPI, size in bytes, format
Param999,,Assem1, $ T=>O RPI, size in bytes, format
,, $ config part 1 (dynamic assemblies)
,, $ config part 2 (module configuration)
"Exclusive Owner", $ connection name
"", $ Help string
"20 04 24 01 2C 70 2C 64"; $ exclusive owner path
Connection2 =
0x02010002, $ TRIGGER AND TRANSPORT MASK
$ BIT=VAL DESCRIPTION
$ 0 = 0 (class 0:null)
$ 1 = 1 (class 1:dup. detect)
$ 2 = 0 (class 2:acknowledged)
$ 3 = 0 (class 3:verified)
$ 4 = 0 (class 4:non-block)
$ 5 = 0 (class 5:non-block, frag)
$ 6 = 0 (class 6:multicast, frag)
$ 7-15 = 0 (class :reserved)
$ 16 = 1 (trigger: cyclic)
$ 17 = 0 (trigger: cos)
$ 18 = 0 (trigger: appl)
$ 19-23 = 0 (trigger: reserved (must be zero))
$ 24 = 0 (transport type: listen-only)
$ 25 = 0 (transport type: input-only)
$ 26 = 1 (transport type: exclusive-owner)
$ 27 = 0 (transport type: redundant-owner)
$ 28-30 = 0 (reserved (must be zero))
$ 31 = 1 (client = 0 / server = 1)
0x44440305, $ CONNECTION PARAMETERS BIT ASSIGNMENTS
$ BIT=VAL DESCRIPTION
$ 0 = 1 (O=>T fixed)
$ 1 = 0 (O=>T variable)
$ 2 = 1 (T=>O fixed)
$ 3 = 0 (T=>O variable)
$ 4-7 = 0 (reserved (must be zero))
$ 8-10 = 4 (O=>T header (4 byte run/idle))
$ 11 = 0 (reserved (must be zero))
$ 12-14 = 0 (T=>O header (pure data))
$ 15 = 0 (reserved (must be zero))
$ 16 = 0 (O=>T connection type: NULL)
$ 17 = 0 (O=>T connection type: MULTI)
$ 18 = 1 (O=>T connection type: P2P)
$ 19 = 0 (O=>T connection type: RSVD)
$ 20 = 0 (T=>O connection type: NULL)
$ 21 = 1 (T=>O connection type: MULTI)
$ 22 = 0 (T=>O connection type: P2P)
$ 23 = 0 (T=>O connection type: RSVD)
$ 24 = 0 (O=>T priority: LOW)
$ 25 = 0 (O=>T priority: HIGH)
$ 26 = 1 (O=>T priority: SCHEDULED)
$ 27 = 0 (O=>T priority: RSVD)
$ 28 = 0 (T=>O priority: LOW)
$ 29 = 0 (T=>O priority: HIGH)
$ 30 = 1 (T=>O priority: SCHEDULED)
$ 31 = 0 (T=>O priority: RSVD)
Param999,0,, $ O=>T RPI, size in bytes, format
Param999,,Assem1, $ T=>O RPI, size in bytes, format
,, $ config part 1 (dynamic assemblies)
,, $ config part 2 (module configuration)
"Input Only", $ connection name
"", $ Help string
"20 04 24 01 2C FE 2C 64"; $ exclusive owner path
Connection3 =
0x01010002, $ TRIGGER AND TRANSPORT MASK
$ BIT=VAL DESCRIPTION
$ 0 = 0 (class 0:null)
$ 1 = 1 (class 1:dup. detect)
$ 2 = 0 (class 2:acknowledged)
$ 3 = 0 (class 3:verified)
$ 4 = 0 (class 4:non-block)
$ 5 = 0 (class 5:non-block, frag)
$ 6 = 0 (class 6:multicast, frag)
$ 7-15 = 0 (class :reserved)
$ 16 = 1 (trigger: cyclic)
$ 17 = 0 (trigger: cos)
$ 18 = 0 (trigger: appl)
$ 19-23 = 0 (trigger: reserved (must be zero))
$ 24 = 0 (transport type: listen-only)
$ 25 = 0 (transport type: input-only)
$ 26 = 1 (transport type: exclusive-owner)
$ 27 = 0 (transport type: redundant-owner)
$ 28-30 = 0 (reserved (must be zero))
$ 31 = 1 (client = 0 / server = 1)
0x44440305, $ CONNECTION PARAMETERS BIT ASSIGNMENTS
$ BIT=VAL DESCRIPTION
$ 0 = 1 (O=>T fixed)
$ 1 = 0 (O=>T variable)
$ 2 = 1 (T=>O fixed)
$ 3 = 0 (T=>O variable)
$ 4-7 = 0 (reserved (must be zero))
$ 8-10 = 4 (O=>T header (4 byte run/idle))
$ 11 = 0 (reserved (must be zero))
$ 12-14 = 0 (T=>O header (pure data))
$ 15 = 0 (reserved (must be zero))
$ 16 = 0 (O=>T connection type: NULL)
$ 17 = 0 (O=>T connection type: MULTI)
$ 18 = 1 (O=>T connection type: P2P)
$ 19 = 0 (O=>T connection type: RSVD)
$ 20 = 0 (T=>O connection type: NULL)
$ 21 = 1 (T=>O connection type: MULTI)
$ 22 = 0 (T=>O connection type: P2P)
$ 23 = 0 (T=>O connection type: RSVD)
$ 24 = 0 (O=>T priority: LOW)
$ 25 = 0 (O=>T priority: HIGH)
$ 26 = 1 (O=>T priority: SCHEDULED)
$ 27 = 0 (O=>T priority: RSVD)
$ 28 = 0 (T=>O priority: LOW)
$ 29 = 0 (T=>O priority: HIGH)
$ 30 = 1 (T=>O priority: SCHEDULED)
$ 31 = 0 (T=>O priority: RSVD)
Param999,0,, $ O=>T RPI, size in bytes, format
Param999,,Assem1, $ T=>O RPI, size in bytes, format
,, $ config part 1 (dynamic assemblies)
,, $ config part 2 (module configuration)
"Listen Only", $ connection name
"", $ Help string
"20 04 24 01 2C FF 2C 64"; $ exclusive owner path
[Port]
Port1 =
TCP,
"EtherNet/IP Port",
"20 F5 24 01",
1;
[Capacity]
MaxIOConnections = 2;
MaxMsgConnections = 2;
MaxConsumersPerMcast = 2;
TSpec1 = Rx, 224, 1000;
TSpec2 = Tx, 480, 1000;
Hi,
I need to write an application (client/scanner) that establishes a communication with an ETHERNET/IP adapter/server using both explicit and implicit(I/O) messaging.
The adapter will be coded in C/C++ using EIPStackGroup/OpENer library.
So, my questions are:
Is This library meant for that ?
Which is the max polling rate ?
I Thank in advance for the answers.
Sérgio
[DEBUG] Connecting to 192.168.11.30:44818
terminate called after throwing an instance of 'std::system_error'
what(): Connection refused
We need to read faults from PowerFlex 525 VFD by using DPI Fault Object.
Implementation
vendor::ra
Example
DPIFaultManager manager;
manager.setNewFaultListener([](const DPIFaultObject& obj) {
obj.getFullInformation().faultCode;
});
manager.setTrippedDeviceListener([](bool tripped) {
});
auto si = std::make_shared<SessionInfo>("172.28.1.3", 0xAF12);
while(true) {
manager.handleFaultObjects(si);
// don't forget to sleep a while
};
Hello,
I am experiencing a 10 second timeout in the implicit messaging example. I am able to connect to my device (ConveyLinx-ERSC) and read the assembly. I found #35, which led me to the document that states:
Inactivity/Watchdog Timer
This timer is is used for consuming connections. The timer is loaded with the API of the
Originator-To-Target direction multiplied by the Connection Timeout Multiplier. The timer
is reset whenever valid connection data was consumed. If the timer expires the connection is
considered timed out and will be closed. For the first reception the timer is set to at least 10
seconds.
I'm wondering what I need to do to "consume" the connection or even extend the inactivity timer. I am trying to set up a service that is always monitoring certain bits in the assembly. One option that I have right now is to accept the inactivity timer and set up a new connection, but then I need to somehow listen for the disconnect. Hope that makes sense!
Thank you,
Joey
Hello.
I am using the EIPscanner with a plc and it works perfectly.
But I also have a second device which doesnot have a config assembly. Only input and ouput assemblies.
What do I need to do with the follow line of code to communicate to the device.
parameters.connectionPath = {0x20, 0x04,0x24, 151, 0x2C, 150, 0x2C, 100}; // config Assm151, output Assm150, intput Assm100
Does EIPScanner support a device without input assembly?
Many thanks
Grayson Penzo
2
Hello,
I am new to Ethernet/IP and I am trying to use this library to create an Ethernet/IP Scanner to talk to a Yaskawa MP3300iec which I setup to be an Ethernet/IP Adapter.
I first tested the Discovery Manager example and was able to confirm that the Identity Object had the correct vendor ID for Yaskawa (0x2C). Now I am trying to use the Implicit Messaging example. I believe I need to use implicit messaging to talk to the adapter as it has input and output assemblies. However, I am running into an error when using the example.
Here is the output that is being displayed from the logger:
[DEBUG] Opened socket fd=3
[DEBUG] Connecting to 192.168.1.2:44818
[INFO] Registered session 52
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[ERROR] Message Router error=0x4 additional statuses [0x0]
[WARNING] Attempt to close an already closed connection
[INFO] Unregistered session 52
[DEBUG] Close socket fd=3
According to GeneralStatusCodes.h, the General Status Code error 0x04 is a Path Segment Error. (https://eipscanner.readthedocs.io/en/latest/api/program_listing_file_src_cip_GeneralStatusCodes.h.html?highlight=0x04#program-listing-for-file-generalstatuscodes-h)
I'll attach the connectionPath below with the rest of the example I've modified. However, I'd love to learn more about how the connectionPath should be formatted so I can understand why my path is wrong.
// Implicit Messaging Example
ConnectionManager connectionManager;
ConnectionParameters parameters;
parameters.connectionPath = {0x20, 0x04, 0x2C, 101, 0x2C, 111}; // output Assm101, input Assm111
parameters.o2tRealTimeFormat = true;
parameters.originatorVendorId = 342;
parameters.originatorSerialNumber = 32423;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.t2oNetworkConnectionParams |= 128; //size of Assm111 = 128 bytes
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
parameters.o2tNetworkConnectionParams |= 128; //size of Assm101 = 128 bytes
parameters.originatorSerialNumber = 0x12345;
parameters.o2tRPI = 1000000;
parameters.t2oRPI = 1000000;
parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;
auto io = connectionManager.forwardOpen(si, parameters);
if (auto ptr = io.lock()) {
ptr->setDataToSend(std::vector<uint8_t>(128));
Thanks for your time,
Joseph
Now with the port to windows, we should create a windows CI server along with the existing linux travis server
I have a question about using Implicite Messaging. After some time I found out how to apply my EDS file to the ImplicitMessagingExample.cpp
.
When I run the example the following output is produced:
[DEBUG] Opened TCP socket fd=3
[DEBUG] Connecting to 192.168.0.2:44818
[INFO] Registered session 748366592
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Open IO connection O2T_ID=2b9d32 T2O_ID=63cf0001 SerialNumber 1
[DEBUG] Opened UDP socket fd=4
[INFO] Open UDP socket to send data to 192.168.0.2:2222
[DEBUG] Opened UDP socket fd=5
[WARNING] Connection SeriaNumber=1 is closed by timeout
[INFO] Closed
[DEBUG] Close UDP socket fd=4
[WARNING] Attempt to close an already closed connection
[DEBUG] Close UDP socket fd=5
[INFO] Unregistered session 748366592
[DEBUG] Close TCP socket fd=3
The corresponding wireshark dump can be found in the attached file. implicitMessagingExample.zip
In the Wireshark dump one can see the following:
No. Time Source Source Port Destination Protocol Dest Port Length Info
27 2.455733 192.168.0.2 2222 192.168.0.5 CIP I/O 2222 70 Connection: ID=0x63CF0001, SEQ=0000000084, T->O
31 3.314139 192.168.0.5 64662 192.168.0.2 CIP I/O 2222 74 Connection: ID=0x002B9D32, SEQ=0000000001, O->T
36 3.455587 192.168.0.2 2222 192.168.0.5 CIP I/O 64662 70 Connection: ID=0x63CF0001, SEQ=0000000085
38 4.338032 192.168.0.5 64662 192.168.0.2 CIP I/O 2222 74 Connection: ID=0x002B9D32, SEQ=0000000002, O->T
39 4.455630 192.168.0.2 2222 192.168.0.5 CIP I/O 64662 70 Connection: ID=0x63CF0001, SEQ=0000000086
47 5.372058 192.168.0.5 64662 192.168.0.2 CIP I/O 2222 74 Connection: ID=0x002B9D32, SEQ=0000000003, O->T
48 5.455641 192.168.0.2 2222 192.168.0.5 CIP I/O 64662 70 Connection: ID=0x63CF0001, SEQ=0000000087
There is traffic from target to originator and vice versa. But none of these packages is printed in the example program.
What looks strange to me is the fact that the connection ID=0x63CF0001 changes the port between package 27 and 36.
Is there something I did wrong?
Best regards
Mario
Hi,
I would like to know if EIPScanner supports I/O messaging through multicast addresses?
I tried to set o2tNetworkConnectionParams and t2oNetworkConnectionParams with NetworkConnectionParams::MULTICAST without success.
If it is supported, do you have any example?
Thanks for this nice project,
Vincent
Describe the bug
Buffer decodes\encodes a float as 16bit data and a double as 32bita data
To Reproduce
TEST(TestBuffer, ShouldDecodeFloat) {
float val = 10.5;
std::vector<uint8_t> expectedData = {0, 0, 0x28, 0x41};
Buffer buffer;
buffer << val;
EXPECT_EQ(expectedData, buffer.data());
}
Output:
xpected equality of these values:
expectedData
Which is: { '\0', '\0', '(' (40, 0x28), 'A' (65, 0x41) }
buffer.data()
Which is: { '\n' (10, 0xA), '\0' }
Environment (please complete the following information):
Hello,
First of all many thanks for the efforts on EIPScanner, with some hacks I managed to get all features working. These "hacks" were mostly needed on Windows (MinGW) due to some inconsistencies/use of deprecated functions. I didn't test on Linux but I don't believe we have the same issues there as the used socket functionality returns as expected.
I'm currently doing some work on replacing these hacks for some actual implementations that can be pushed back to the library but before I do so I would like some more opinions about the topics at hand (I will make specific tickets where needed later).
errno is not set (always zero), resulting in undefined behavior as the result of this is used throughout the library. WSAGetLastError() should be used instead and use the respective WSA error codes (e.g. WSAEAGAIN).
E.g. the discovery scanner depends on a return of EAGAIN from the receive function causing it to fail. I would expect the same Linux behavior (https://man7.org/linux/man-pages/man3/recvfrom.3p.html) on Windows but the documentation is limited on this (https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom).
inet_addr(...) is deprecated after Windows XP and actually failing on later versions (i.e. returns INADDR_NONE with the empty string passed in e.g. discovery manager, where defined behavior should be INADDR_ANY. Replace with inet_pton(...) on Windows and optionally keep inet_addr in there with some Windows <= XP version check for backwards compatibility.
E.g. this monstrosity in Endpoint.cpp:
#if defined(__linux__) || defined(__APPLE__)
if (inet_aton(_host.c_str(), &_addr.sin_addr) < 0) {
#elif defined _WIN32
#if (_WIN32_WINNT >= 0x0600) //Windows Vista and later
if (inet_pton(AF_INET, _host.c_str(), &_addr.sin_addr.s_addr) < 0) {
#else //Windows XP and before (deprecated)
if ((_addr.sin_addr.s_addr = inet_addr(_host.c_str())) == INADDR_NONE) {
#endif
#endif
throw std::system_error(errno, std::generic_category());
}
Empty (0.0.0.0) socket address info T -> O included in forward open request
With the 0.0.0.0 socket address information command specific data included, my EIP devices attempt to send back to 0.0.0.0. I'm pretty sure the address info section should A) be removed or B) already set to the local endpoint. I believe A is according to specifications, it should not be in the FW open request at all. I will check the specs later to be sure but implementing either A) or B) works for me
Hello,
I have your implicit messaging example working for my device (ConveyLinx-ERSC) and outputting the correct assembly. I am receiving a message on 1 second intervals and I am wondering if it's possible to decrease that interval to 100ms or faster.
I also wanted to thank you for creating this library!
Thank you,
Joey
Hi, thank you for the project! I successfully built it for OpenWRT with Linaro toolchain (with backport to Cpp11) and it works perfectly.
But I need additional functionality - to read the tags (I/O) from Rockwell PLC (by CIP).
Do something like:
messageRouter.readTag(si, "arrayTag[0]")
(like it's implemented here: https://github.com/cmseaton42/node-ethernet-ip)
I'm completely newbie in EthernetIP and CIP but I can develop (and contribute to the project)
if you point me the right manual - how to encapsulate CIP request into Ethernet/IP frame and get the answer.
Thank you!
I want to separate vendor objects from the library's main CMakeLists.txt, so they are not required with every build. Allow for users to set a flag in cmake to compile them in conjunction with main library.
Is your feature request related to a problem? Please describe.
The library doesn't support types:
Describe the solution you'd like
We need to add type definitions and stream methods into utils::Buffer
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.