Cpp networking and RSC service

Hi everyone, I’m trying to use the RSC service and the network capabilities of Cpp.

I looked in the documentation to implement the network functions and the RSC service but I’m not so familiar with Cpp.
I found an example of the Net socket functions I need in the following link: https://api.plcnext.help/api_docs_2020-0-LTS/classArp_1_1System_1_1Commons_1_1Net_1_1Socket.html I tried the same functionalities in the Csharp code but programming in Cpp is more complex. I’m trying to use the work thread for the network functions. I also want to try out the RSC services so I would like to be able to write an read an array of 512 bytes to the real time operation of the PLC.
I noticed this was possible with Arrayread and Arraywrite. But ones again I’m not quite sure how to do it. Is it possible to get some help about those topics? Greetings,
Arne

Hi Arne, Sorry for the delay. There are two parts to your question: 1. Using sockets in C++. If you followed the example in the documentation, are you able to explain what didn’t work in your case, perhaps showing where your code failed? 2. Write and read an array of 512 bytes to the real time operation of the PLC. If these byte arrays you want to read & write to are defined in the Global Data Space (e.g. I/O variables, or port variables in a PLCnext Engineer project, for example), and if your C++ program (or component) knows the names and types of these GDS ports at design-time or at startup, then the best way to achieve this is using port variables in your own C++ program/component. You can then link the port variables in your C++ program/component to other port variables of the same type, using a .gds.config file, or else in PLCnext Engineer, depending on your application. If your C++ code does not know the name, number and/or types of GDS ports it want to read/write before it is started by the PLCnext Runtime, then you will need to use an RSC service to read and write these variables. But since this is a more complex solution, it should only be done if the other method (using port variables in your program/component) is not suitable. If you are able to tell us more about your application’s requirements, then perhaps we can advise on the best approach. ~ Martin.

Hi Martin, I posted the code in an github repository so you could check it out. https://github.com/ArneBert/Cpp-PLCnext-TCP Using socket C++ The problem I have is that Eclipse doen’t recongnize the Socket name. I included the Arp::system:…//Socket.hpp. Write array and read array I know I’m making it complicated with the use of the RSC services and it could be done with the IN- and OUT-ports. I defined two arrays of 512 bytes as an IN- and OUT-port. If I get it to work with the Socket to send the data I will be very happy. I just thougth it would be nice to know if this service call takes a lot of time to get that data. Greetigns, Arne


Hi Arne, 1. Using sockets in C++. I think the example in the documentation of the Socket class isn’t great. Instead, try something like this:

                                               * In the component header file:

#include "Arp/System/Commons/Net/Socket.hpp"

using namespace Arp::System::Commons::Net;

private:  
>     std::shared_ptr&ltSocket;> listeningSocket;

                                               * In the component .cpp file, e.g. in the SetupConfig method:

listeningSocket = std::make_shared&ltSocket;>(SocketType::Tcp, SocketDomain::Ipv4, SocketBlockingMode::Blocking);

That should get you a Socket object that you can use. 2. Write and read an array of 512 bytes to the real time operation of the PLC. You would do this using the “Read” and “Write” methods of the “Data Access” RSC service. Before trying this, you should be comfortable using the “ReadSingle” and “WriteSingle” methods on that same RSC service, since those are much simpler methods (because they don’t require the use of delegates). Can you confirm that you are able to successfully read and write single GDS variables (not arrays, just primitive types) using the Data Access RSC service? After that, you can take the next step to using the Read and Write methods.

Hi Martin, I made an update on the GitHub page. But I have some issues with the corrections you proposed. **Socket:

** The listeningSocket is fixed but I can’t use any function I need such as bind, listen and accept. work-thread
I’m having some trouble with building the cpp because of the inline procedure just under the public ports Tthe IComponent::Ptr isn’t recognised by Eclipse.
How do I need to implement the work-thread in my execute program to use the IN- and OUT-Ports of the array with 512 bytes ?

**RSC
** I tried to acces a primitive type but I’m having some issues about getting to read and write the data.I created a ReadItem and WriteItem in the component.hpp and tried to acces it in the Program.cpp but unfortunately, It doen’t recognise the readItem and WriteItem. I have posted some pictures to show what the problems are. Greetings, Arne



Hi Arne, Socket:

listeningSocket is a smart pointer, so you’ll need to use the arrow operator -> to reference methods and fields on the object. work-thread
I don’t think that IComponent::Ptr “error” is a problem - Eclipse often marks valid code like this, for some reason. Does the code compile? If not, what error messages do you see from the compiler? RSC
The Data Access service can only be used to access variables that appear in the Global Data Space. In PLCnext Engineer, this means that the variables must be declared as either IN PORT or OUT PORT variables (not External). You will be able to read and write to IN PORT variables, but only read from OUT PORT variables. You will be able to see the fully qualified name of the GDS variable (including the Program Instance name) in the PLCnext Engineer “PLCnext → Port List” window. You need to pass this fully-qualified GDS variable name to the ReadSingle and WriteSingle methods of the Data Access service.

Hi Martin, First of all thanks for the help you are giving me. **Socket

** So as you suggested the listening is a new pointer. I changed the bind and listening to this smart pointer but the Accept won’t work (see picture 2020-06-02 (2).png). Also the NewSocket didn’t work but I made it as same as the listeningSocket. Work-thread.
I attached a picture to show you the error of the Icomponent::ptr (see picture 2020-06-02.png). **RSC
** So I tried different things to learn to work with those ReadSingle() and WriteSingle() but I’m stuck implementing it. I made 2 inports in the PLCnext DW_IN1 and DW_OUT1 → these are the adresses in the PLCnext “Arp.Plc.Eclr/main1.DW_IN1” and “Arp.Plc.Eclr/main1.DW_OUT1”. I made 2 IN-Ports because one is to read and the other one is to write the values. Could you tell me what I’m doing wrong with those methodes? I’m geussing I’m implementing them at the cpp or hpp file.
In an other test I did which is not included in the github page. I tried to use this: std::shared_ptr But I couldn’t make it to work either. Thx again in advanced. https://github.com/ArneBert/Cpp-PLCnext-TCP Greetings, Arne


Hi Arne, Those compilation errors are saying that you have not implemented the Start and Stop functions in your Component, which is required if your component implements IControllerComponent. You can either implement these methods (if you need to take action when the PLC starts or stops), or else remove IControllerComponent from the component class declaration. The problem with the Accept method appears to be with the first parameter - it looks like it is expecting an IpAddress object, not an IpAddress::IpV4Value. Again, it looks like the sample code in the API documentation might be misleading or just wrong. Please be aware of which calls will block the execution of the thread (e.g. listening for a client connection), and what impact that will have on your application. For the RSC service: There is information in the Info Center on how to use RSC services. https://www.plcnext.help/te/Service_Components/Remote_Service_Calls_RSC/Using_RSC_services.htm As shown in that link, it is necessary to:

                                               * include the relevant header file for the service you want to use (e.g. Arp/Plc/Gds/Services/IDataAccessService.hpp),
                                               * declare a pointer to the service,
                                               * retrieve a handle (pointer) to the service using the ServiceManager::GetService function.

Then, you can use the service handle to call the methods on that service, e.g. “ReadSingle” on the Data Access service. Please also note the advice in the Info Center, that you should avoid direct calls to RSC services from ESM tasks. For C++ programs, the Execute method of a program is called from an ESM task, so it should not include calls to RSC services. Instead, RSC service calls should be made from non-real-time components.

Hi Martin, I have some difficulties with building the application. I implemented the start en stop functions of the component to start and stop the work thread.

But know I have some issues within the cpp component (see picture). https://github.com/ArneBert/Cpp-PLCnext-TCP
I
tried to solve it myself but I’m not understanding what’s wrong with it. Is it possible to get the data stored in the arrayread and arraywrite in the work thread to the execution of the program?
I tried it with a typedef in the program.hpp but without any succes. thanks for the help. Greetings,
Arne

Hi Arne, The compiler is saying that there is a redefinition of the CppRSCServiceComponent constructor. In your project, this constructor appears in both the .hpp and the .cpp file. You can delete one of these, probably the one in the .hpp file (so it matches the default template generated by eclipse). If you declare your arrays in the Component, then this data can be accessed from your workerThreadBody method, just like the other variables are (e.g. listeningSocket). Also, since the Program has a reference to the component (through your program’s cppRSCServiceComponent variable), it can also access data that is declared in the component, if necessary. ~ Martin.

Hi, I’m back working on this topic. I updated the github page, t he CppRSCService_v2 is the newest version. I managed to get data from the PLCnext Controller to the Siemens PLC and back I think.

The problem I’m having at the moment is to get the data out of the component.cpp file to the program.cpp, where I can use it in the PLCnext Engineer through the IN- and OUT-ports. I would like to get the following data in the program.cpp: -array of 512 from the PLCnext to the Siemens (recieved by the IN-port).
this is the data array, to send to the Siemens PLC
-array of 512 from the Siemens to the PLCnext (send to the OUT-port)
this is the data array, I will recieve from the Siemens PLC
- 3 int32 values about different times things are handled. (send to the OUT-port)
These values are the different timestamps I will use. Greetings,
Arne

Hello Arne,

what version of the plcnext FW / SDK are you using?
Are you implementing this as an ACF Component or a PLM Component (Component for Programs…)?
You could maybe also use a Component Port (One Struct with In and Out parameters).

Otherwise you can access the contents of your Component in the Program directly or generate some methods that feed the Data.

something like Program::Execute(){
SomeData = ComponentName.GetData();
ComponentName.SetData(SomeData);
}

Hi, I’m using eclipse with PLCnCLI version 2020.0 LTS (20.0.0.24752) and the PLCnext Controller AXC-F-2152 is also version 2020.0 LTS (20.0.0.24752)

It is a program or PLM. Here is the link to the github page: https://github.com/ArneBert/Cpp-PLCnext-TCP/tree/master/CppRSCService_v2
I will try the method you metion and give you an answer if it worked or not. Greetings,
Arne

Hi all, I tried the method Olivier pointed out, but without any succes. I guess there needs to be an other method for doing this but I’m unable to find this method. The IN-Port of the array of 512 bytes to read and written, in the IProgramclass needs to be accesable to the workthread in the Icomponentclass.

The github link has not been updated since because I was unable to find the solution to this problem. https://github.com/ArneBert/Cpp-PLCnext-TCP/tree/master/CppRSCService_v2
Is it possible to get some help about this topic? Maybe a question off topic, but on which framework the C++ used in Eclipse is based? Greetings,
Arne