FESA3 C++ Code Snippets

Working with devices in the server-part

// Since server actions are only executed for a specific device,
// we directly can use the argument "pDev", which is passed to the execute-method
pDev->myField.set(someValue,pEvt->getMultiplexingContext());

// In Server-Actions the global-device can be accessed by using the service-locator
MyClassServiceLocator_->getGlobalDevice()->myField.set(someValue,pEvt->getMultiplexingContext());

For the complete API of the class "device" and it's relatives, check the doxygen documentation.

Working with devices in the RT-part

// In a RT-Action we can iterate over the whole device-collection like that:
std::vector<Device*>::iterator device;
for(device=deviceCol_.begin();device!=deviceCol_.end();++device)
{
   // perform some action with the device
   (*device)->myField.set(someValue,pEvt->getMultiplexingContext());
}

// In RT-Action global-fields can be accessed by using the service-locator
MyClassServiceLocator_->getGlobalDevice()->myField.set(someValue,pEvt->getMultiplexingContext());

For the complete API of the class "device" and it's relatives, check the doxygen documentation.

Working with devices in the specificInit methods

#include <fesa-core/Synchronization/NoneContext.h>
#include <MyClass/GeneratedCode/DeviceFactory.h>//put in the name of your class

//Since an empty context is needed to access any field, you can make use of the fesa-internal-type "NoneContext"
fesa::NoneContext context;

// In the method "specificInit" of the RT/Server-DeviceClass a member "devCol_" is not provided to access devices.
// For now, we have to use the DeviceFactory to obtain device-references outside of the Server/RTAction
// Later this job will be done by the Service-Locator
const std::vector<Device*> devCol = DeviceFactory::getInstance()->getDeviceCollection();
GlobalDevice* globalDev = DeviceFactory::getInstance()->getGlobalDevice();

std::vector<Device*>::const_iterator device;
for(device= devCol.begin();device!=devCol.end();++device)
{
    std::cout << "DeviceName: " << (*device)->getName() << std::endl;
    (*device)->myField.set(someValue,&context);
}

Working with FESA scalar-fields

int32_t myData = (*device)->myField.get(pEvt->getMultiplexingContext());
myData ++;
(*device)->myField.set(myData,pEvt->getMultiplexingContext());

For the complete API of scalar-fields and it's relatives, check the doxygen documentation.

Working with FESA array-fields

// Set data to a array-field:
uint32_t sizeOfmyData = 4;
int32_t myData[sizeOfmyData];
myData[1] = 15;
(*device)->myArrayField.set(myData,sizeOfmyData,pEvt->getMultiplexingContext());

// Get data from a array-field:
uint32_t dim;
const int32_t* myData = (*device)->myArrayField.get(dim,pEvt->getMultiplexingContext());

For the complete API of array-fields and it's relatives, check the doxygen documentation.

Working with FESA 2D-array-fields

uint32_t index1 = 1;
uint32_t index2 = 1;
uint32_t dim1 = 3;
uint32_t dim2 = 2;

//Get a cell-value
const int32_t myData = (*device)->my2DArray.getCell(index1,index2,pEvt->getMultiplexingContext());

//Set a cell-value
int32_t myNewData
(*device)->my2DArray.setCell(myNewData,index1,index2,pEvt->getMultiplexingContext());

//Get a row
const int32_t* myData =  (*device)->my2DArray.getRow(index1,dim1,pEvt->getMultiplexingContext());

//Set a row/column
uint32_t index = 1;
int32_t myDataColumn[dim2];
int32_t myDataRow[dim1];
(*device)->my2DArray.setColumn(myDataColumn,index,dim2,pEvt->getMultiplexingContext());
(*device)->my2DArray.setRow(myDataRow,index,dim1,pEvt->getMultiplexingContext());

//Get the complete array2D
uint32_t dim1;
uint32_t dim2;
const int32_t** myDataAll = (*device)->my2DArray.get(dim1,dim2,pEvt->getMultiplexingContext());

For the complete API of 2D-array-fields and it's relatives, check the doxygen documentation.

Working with FESA char-array-fields (strings)

std::string myString;
(*device)->myCharArray.set(myString.c_str(),pEvt->getMultiplexingContext());

const char* myCharArrayPointer = (*device)->myCharArray.get(pEvt->getMultiplexingContext());

For the complete API of string-fields and it's relatives, check the doxygen documentation.

Working with FESA 2D-char-array-fields (string-arrays)

uint32_t index = 0;
std::string myString = "MyString";
(*device)-->myCharArray2D.setString(myString.c_str(), index,pEvt->getMultiplexingContext());

const char* myCharArrayPointer = (*device)->myCharArray2D.getString(index,pEvt->getMultiplexingContext());

For the complete API of string-array-fields and it's relatives, check the doxygen documentation.

Working with bit-enum-fields

// generated code in TypeDefinition.h (just an example):
namespace MyBitEnum
{
   enum MyBitEnum
   {
      isActive=1,
      isValid=2,
      hasPower=4
   }; // 3 bits 
}

// Access the field in Server/RT-Actions:
uint32_t value = MyBitEnum::isActive | MyBitEnum::hasPower;
(*device)->myBitEnumField.set(static_cast<MyBitEnum::MyBitEnum>(value) ,pCtxt);

uint32_t newValue = (*device)->myBitEnumField.get(pEvt->getMultiplexingContext());

Fill the GSI-Multiplexing-context-field

//stamp should be in Nanoseconds - UTC
int64_t stamp = 12345678;
(*device)->acquisitionContext.setacqStamp(stamp,pEvt->getMultiplexingContext());
(*device)->acquisitionContext.setcycleName(const_cast<char*>(pCtxt->getCycleName().c_str()),pEvt->getMultiplexingContext());
(*device)->acquisitionContext.setcycleStamp(pCtxt->getCycleStamp(),pEvt->getMultiplexingContext());

Report an error by using the GSI-error_collection-field

std::string errorString= "Put in your error-text here";
long error_code= 4711;
(*device)->error_collection.addError(error_code,errorString,pEvt->getMultiplexingContext(),*device);

For the complete API of the class "GSIErrorCollectionField" and it's relatives, check the doxygen documentation.

Usage of class-specific custom-types

// Take a look into "generated/cpp/MyClassName/GeneratedCode/TypeDefinition.h" to see all custom-types, defined by your class
(*device)->control.set(DEVICE_CONTROL::LOCAL,pEvt->getMultiplexingContext());

Usage of client-data in server-actions

//In a Set-Server-Acttion you may want to retrieve the data and the filter, which was send by the client:
bool myData = data.myValueItemName.get();
bool myData = filter.myFilterItemName.get();

//In a Get-Server-Action you may want to fill the data-container which will be send to the client.
int32_t myData = 1234;
data.myValueItemName.set(myData );

Usage of external headers and libraries

# Modify the file "Makefile.specific" of your class / deploy-unit, according to your needs
SOME_LIBRARY_HOME= /path/to/the/library
COMPILER_FLAGS += -I$(SOME_LIBRARY_HOME)/include
LINKER_FLAGS += -L$(SOME_LIBRARY_HOME)/lib/$(CPU) -lsome-library

Usage of the FESA-Logger

std::ostringstream message;
message << "Put your logg-message here " ;
LOG_ERROR_IF(logger, message.str());
// Depending on how important your logg-message is, you should use one of the following macros:
// LOG_TRACE_IF(logger, message.str());
// LOG_DEBUG_IF(logger, message.str());
// LOG_INFO_IF(logger, message.str());
// LOG_WARNING_IF(logger, message.str());
// LOG_ERROR_IF(logger, message.str());

  • Use the application-arguments -v and -vv to control the verbosity of your FESA-Software
  • If needed you as well can re-configure the logging-configuration by providing a foreign config-file (Application-Argument -cfglog )
  • Information on where the log-files are stored can be found here.
  • As well check doxygen documentation of the complete logger API.

How to trigger an on-demand-event manually

// First you have to choose "@automatic = false" on your action/triggered-event-source in the class-design 
// In the server/rt-action, you can fire the event with the following command:
AbstractAction::triggerOnDemandEventSource("MyOnDemandEventSource",pEvt->getMultiplexingContext(),0);

// If required, you as well can add some payload-information
std::string payload = "myPayload";
AbstractAction::triggerOnDemandEventSource("MyOnDemandEventSource",pEvt->getMultiplexingContext(),payload.c_str(),payload.size(),0);

// In the RT-Action you than can read-out the defined payload like that:
#include <fesa-core/RealTime/RTEventPayload.h>
....
std::string payload = pEvt->getPayload()->getValue<char>();

For the complete API of the class "AbstractAction" and it's relatives, check the doxygen documentation.

How to trigger a property-notification manually

//Currently the usage of manual-notifications is only possible in rt-actions.
//In a later release the same concept will apply for server-actions

//Include the Header where the class "ManualNotificationMessage" is defined:
#include <fesa-core/Core/MessageTypes.h>

//Make sure that the names of the property/device you want to notify are correct
std::string notifiedProperty = "MyProperty";
std::string notifiedDevice = "MyDevice";

//You can add any number of property/device-combinations by using the following method:
manualNotificationMessage_->addPropertyAndDevice(notifiedProperty,notifiedDevice);

//If you are finished with adding properties/devices, send the notification by using the method below
sendManualNotification(pEvt->getMultiplexingContext());

Throwing Exceptions to clients

In Server-Actions one can use the different RDA-Exception-classes to throw an exception:

#include <cmw-rda/Exception.h>
...
std::string errorCategory = "MyCategory";
long errorCode = 4711;
std::string errorMessage = "Something went wrong!";

// If you are a class-developer you throw IO Errors.
// errorCategory should be "FESACLASS_" as prefix an the classname.
// Example: "FESACLASS_DcMagnet"

throw rdaIOError(errorCategory.c_str(), errorCode, errorMessage.c_str());
throw rdaBadParameter(errorMessage.c_str());
throw rdaTypeMismatch(errorMessage.c_str());
throw rdaTimeOut(errorMessage.c_str());
throw rdaNoConnection(errorMessage.c_str());
throw rdaNoPermission(errorMessage.c_str());

Currently at GSI there are no standards regarding the error-codes and the error-category.
Topic revision: r20 - 24 Apr 2013, MatthiasWiebel
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