SILECS C++ Code Snippets

- General -

Specific Init

In order to make the generated silecs-code work, you need to initialize it in the specifc-init of your class (usually in RealTime/ RTDeviceClass.cpp)

// Repalce "MyClass" with the name of your class

// include the silecs header
#include <MyClass/Common/MyClass.h>
...
RTDeviceClass::~RTDeviceClass()
{
   MyClass::cleanup();
}

void RTDeviceClass::specificInit()
{
   MyClass::setup(this->MyClassServiceLocator_);
}

- Access of PLC-blocks -

Working with READ-ONLY blocks

Best read the PLC-values periodically in the RT-Action:
// include the silecs header
#include <MyClass/Common/MyClass.h>
...
// Repalce "MyClass" with the name of your class
// Repalce "MyBlock" with the name of the block you want to read
std::vector<Device*> devCol = this->MyClassServiceLocator_->getDeviceCollection();
std::vector<Device*>::iterator device;
for(device=devCol.begin();device!=devCol.end();++device)
{
   MyClass::MyBlock.getOneDevice((*device),true,pEvt->getMultiplexingContext());
}

If the Block is connected to a FESA-Property, you can read the PLC value in the FESA Get-Server-Action of that Property instead. In order to do so, set the FESA field-attribute "shared" to "false". Please note that in this case, the FESA-field will not be available on the FESA RT-side.

<field name="myRegister" multiplexed="false" persistent="false" shared="false">
   <scalar type="int16_t" />
</field>
#include <MyClass/Common/MyClass.h>
...
void getMyBlock::execute(fesa::RequestEvent* pEvt, Device* pDev, myBlockPropertyData& data)
{
    MyClass::MyBlock.getOneDevice(pDev,true,pEvt->getMultiplexingContext());
}

Working with WRITE-ONLY blocks

TODO: Actually a WRITE-ONLY block should generate a FESA-command property ... currently a setting property is generated: See bugzilla bug

So currently, if the Silecs-block is connected to a FESA property, best change the type of the property to "command-property", or create a fresh command-property and copy the needed value-items to there. If preferred you instead can throw an exception when the Get-Server-Action is triggered.

The plc-value of WRITE-ONLY blocks can be written for all devices in a FESA RT-Action:
// include the silecs header
#include <MyClass/Common/MyClass.h>
...
// Repalce "MyClass" with the name of your class
// Repalce "MyBlock" with the name of the block you want to write
std::vector<Device*> devCol = this->MyClassServiceLocator_->getDeviceCollection();
std::vector<Device*>::iterator device;
for(device=devCol.begin();device!=devCol.end();++device)
{
   MyClass::MyBlock.setOneDevice((*device),true,pEvt->getMultiplexingContext());
}

Or for a specific device in a Set-Server-Action:
#include <MyClass/Common/MyClass.h>
...
void setMyBlock::execute(fesa::RequestEvent* pEvt, Device* pDev, myBlockPropertyData& data)
{
    pDev->myRegister.set(data.getMyRegisterSet(),pEvt->getMultiplexingContext()); // first update the FESA-field with the incoming values
    MyClass::MyBlock.setOneDevice(pDev,true,pEvt->getMultiplexingContext());
}

For WRITE-ONLY fields there should be no need to set the field-attribute "shared" to false.

Working with READ-WRITE blocks

In order to use the different Silecs-Methods, you currently need to add the attribute @data-consistent=false to each FESA-field which refers to a RW-register. Caution: Only use this attribute together with @shared=false in order to dont have the risk of concurrent access. On the server-side, use custom-server-actions in order to get/set the PLC-register.

For reading a READ-WRITE block, please refer to the the documentation of READ-ONLY blocks

For writing a READ-WRITE block, please refer to the the documentation of WRITE-ONLY blocks

Reading out the current PLC run-state

//currently it is required to decode the returned status-integer by hand. For Siemens PLC's the following codes are used by step7:
#define S7CpuStatusUnknown  0x00
#define S7CpuStatusRun      0x08
#define S7CpuStatusStop     0x04

....

// Repalce "MyClass" with the name of your class
std::vector<Device*> devCol = this->MyClassServiceLocator_->getDeviceCollection();
std::vector<Device*>::iterator device;
for(device=devCol.begin();device!=devCol.end();++device)
{
   Silecs::Cluster* cluster = SIS100InjKicker::theCluster();
   Silecs::PLC* pPLC = cluster->getPLC((*deviceMaster)->plcHostName.get(),(*deviceMaster)->parameterFile.get());
   Silecs::UnitStatusType statusStruct;
   pPLC->recvUnitStatus(statusStruct); // will throw exception on fail
   switch (statusStruct.status)
   {
      case S7CpuStatusRun : std::cout << "PLC Status is:  RUN" << std::endl; break;
      case S7CpuStatusStop: std::cout << "PLC Status is:  STOP" << std::endl; break;
      default             : std::cout << "PLC Status is:  UNKNOWN" << std::endl); break;
   }
}

Reading out global plc information

Like the PLC run-state, as well the other plc parameters can be obtained. Here the available methods on plc level:
...
Silecs::UnitCodeType unitCodeStruct;
int ret = pPLC->recvUnitCode(unitCodeStruct);

Silecs::CPUInfoType cpuInfoStruct;
int ret = pPLC->recvCPUInfo(cpuInfoStruct);

Silecs::CPInfoType cpInfoStruct;
int ret = pPLC->recvCPInfo(cpInfoStruct);

...

for a full List of all available actions on plc-level, check: https://sourceforge.net/p/silecs/git/ci/gsi/tree/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h

Get a specific PLC-register

The silecs internal class "SilecsRegister" provides many options which can be used. Here just one example.

To see all provided methods, check: https://sourceforge.net/p/silecs/git/ci/gsi/tree/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h
// Repalce "MyClass" with the name of your class
// Replace "MyClass" with the name of your class
// Replace "myRegisterName" with the name of your register
// Replace "MySettingBlock" with the name of your block
for(device=devCol.begin();device!=devCol.end();++device)
{
   Silecs::PLC* pPLC = cluster->getPLC((*deviceMaster)->plcHostName.get(),(*deviceMaster)->parameterFile.get());
   Silecs::Device* plcDevice = pPLC->getDevice((*deviceMaster)->plcDeviceLabel.get());
   Silecs::Register* plcRegister = plcDevice->getRegister("myRegisterName");

   // BYTE values internally are stored as uchar ... check the conversion List on SilecsRegister.h to see what is the correct data-type to use here
   plcDevice->recv("MySettingBlock");//update local block-data
   int value = (int)plcRegister->getValUChar();
   std::cout << " old value: " << (int)value << std::endl;
   plcRegister->setValUChar((unsigned char)(value + 1)); // set new value in silecs
   plcDevice->send("MySettingBlock");//send data to PLC for a specific block
   plcDevice->recv("MySettingBlock");//update data from PLC for a specific block
   std::cout << " new value: " << (int)plcRegister->getValUChar() << std::endl;
   //oder auch:
   plcRegister->printVal();
}

Dependency in Makefile.specific

In order to build and links against the silecs library and snap7 you will need to add some line to the FESA makefile Makefile.specific. Replace the concrete version with the one you want to use.

For fesa classes:
...
SILECS_VERSION ?= 2.1.3
SILECS_BASE ?= /common/usr/cscofe/silecs
SILECS_COM ?= $(SILECS_BASE)/silecs-communication-cpp/$(SILECS_VERSION)

COMPILER_FLAGS += -I$(SILECS_COM)/include
...

For fesa deploy units:
...
SILECS_VERSION ?= 2.1.3
SILECS_BASE ?= /common/usr/cscofe/silecs
SILECS_COM ?= $(SILECS_BASE)/silecs-communication-cpp/$(SILECS_VERSION)
SILECS_SNAP7 ?= $(SILECS_BASE)/snap7/${SILECS_VERSION}

LINKER_FLAGS += -L$(SILECS_COM)/lib/$(CPU) -lsilecs-comm
LINKER_FLAGS += -L$(SILECS_SNAP7)/bin/$(CPU)-linux -lsnap7

#add default search path for dynamic snap7 library
LINKER_FLAGS += -Wl,-rpath,$(SILECS_SNAP7)/bin/$(CPU)-linux,-rpath,/usr/lib
...

This topic: Frontend > WebHome > SILECS > Silecs_1_0_0 > Silecs_1_0_0_CodeSnippets
Topic revision: 29 Apr 2022, AlexanderSchwinn
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback