Beckhoff / ADS

Beckhoff protocol to communicate with TwinCAT devices.
MIT License
491 stars 193 forks source link

AdsSyncReadReqEx2() returns -1 #188

Closed ArsMasiuk closed 1 year ago

ArsMasiuk commented 1 year ago

On Ubuntu, AdsSyncReadReqEx2 returns code "-1" which is not listed anywhere.

What does it mean and how to resolve the issue?

The same call under Windows works pretty fine,

pbruenn commented 1 year ago

I guess it is this one: https://github.com/Beckhoff/ADS/blob/master/AdsLib/standalone/AmsConnection.cpp#L148

Which means AmsConnection::Write() returned a nullptr. If you don't see any other log output this means not all of your data was written to the socket.

ArsMasiuk commented 1 year ago

Yes, it look like so. But what could be the reason? There is a "normal" 1-GB network card, with Jumbo Frames enabled (MTU=9000). Under Windows, it works with no errors. Am I missing something?

pbruenn commented 1 year ago

To confirm our guess you can try this:

diff --git a/AdsLib/Sockets.cpp b/AdsLib/Sockets.cpp
index 9549b05..aa19fc5 100644
--- a/AdsLib/Sockets.cpp
+++ b/AdsLib/Sockets.cpp
@@ -224,6 +224,10 @@ size_t Socket::write(const Frame& frame) const
         LOG_ERROR("write frame failed with error: " << std::strerror(WSAGetLastError()));
         return 0;
     }
+
+    if (frame.size() != (size_t)status) {
+        LOG_ERROR("Only " << std::dec << status << " bytes send, instead of " << frame.size());
+    }
     return status;
 }

Without more info about your specific usecase (hint: show your test code and log output), there is little I can do.

ArsMasiuk commented 1 year ago

Hmm, I dont see these error messages, but there come warnings like:

Warning: Port: 30000 already in use as

So it looks like it is getting failed even before writing to the socket, in AmsConnection::Reserve() at line 119 in AmsConnection.cpp.

I see port 30000 when the app is getting connected to the PLC. The application is multithreaded, so it opens the port in one thread but does further communication in another one. Is it not allowed on Linux?

pbruenn commented 1 year ago

Well, I wouldn't say "it isn't allowed", but yes it isn't expected. If you access the same ams port from different threads you should expect this -1 error. The idea is that ams ports are cheap so simply use one ams port per thread and you don't need to worry about synchronisation. The entire AdsLib is designed around that concept.

ArsMasiuk commented 1 year ago

Ah ok I see... So the application has to be changed in order to access AMS via only one thread in order to get it working on Linux. Thank you Patrick for your help!