FORUM CTRLX AUTOMATION
ctrlX World Partner Apps for ctrlX AUTOMATION
Dear Community User! We will start the migration process in one hour.
The community will be then in READ ONLY mode.
Read more: Important
information on the platform change.
08-03-2021 09:50 AM - edited 08-03-2021 10:35 AM
I want to use multiple different flatbuffers in my application, but I can't register more than one flatbuffer as a type in the data layer.
I extended the datalayer.register.node example to include a second flatbuffer (called sampleScheme2.fbs). Now when I start the application, I always see that registerType fails with the message "DL_INVALID_VALUE" for the second flatbuffer.
If I call registerType for sampleScheme2.fbs first, than sampleScheme.fbs returns "DL_INVALID_VALUE" when calling registerType.
Registering the nodes works without any problems.
Do I have to create a new data layer provider for each flatbuffer?
Solved! Go to Solution.
09-06-2021 01:53 PM - edited 11-22-2021 09:04 AM
Sorry for the late reply.
Of course it is possible to register several flatbuffers in one app. I adapted the registernode example of the SDK for ctrlx AUTOMATION in version 1.10:
// IDL file for sample schema.
namespace mysample.myschema;
table InertialValue { x:short; y:short; z:short; a:short;}
root_type InertialValue;
...
# Flatbuffers
set (FLATBUFFERS_FLATC_EXECUTABLE ${USER_DEPENDENCY_DIR}/bin/oss.flatbuffers/linux-gcc-x64/release/flatc)
set (FLATBUFFERS_INCLUDE_DIR ${USER_DEPENDENCY_DIR}/include/oss.flatbuffers/oss.flatbuffers)
include (${USER_DEPENDENCY_DIR}/cmake/oss.flatbuffers/FindFlatBuffers.cmake)
set( FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS "--gen-object-api")
build_flatbuffers("sampleSchema.fbs" "" "registernodeflatbuffers" "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/bfbs" "")
build_flatbuffers("mysampleSchema.fbs" "" "myregisternodeflatbuffers" "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/bfbs" "")
...
# Define Executables to add from project files and their depending source files
add_executable( ${TARGET_PROJECT_NAME} ${SOURCE_FILES_REGISTERNODE} )
add_dependencies(${TARGET_PROJECT_NAME} registernodeflatbuffers)
add_dependencies(${TARGET_PROJECT_NAME} myregisternodeflatbuffers)
...
#include "sampleSchema_generated.h"
#include "mysampleSchema_generated.h"
...
// Read function of metadata of an object. Function will be called whenever a node should be written.
virtual void onMetadata(const std::string &address, const comm::datalayer::IProviderNode::ResponseCallback &callback) override {
flatbuffers::FlatBufferBuilder builder;
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<comm::datalayer::Reference>>> references;
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<comm::datalayer::Reference>>> references2;
auto emptyString = builder.CreateString("This is a Description");
if (address.compare("myData/myFlatbuffer") == 0) {
flatbuffers::Offset<comm::datalayer::Reference> vecReferences[] = {
comm::datalayer::CreateReferenceDirect(builder, "readType", "types/sampleSchema/inertialValue"), };
references = builder.CreateVectorOfSortedTables(vecReferences, 1); }
else if (address.compare("myData/myFlatbuffer2") == 0) {
flatbuffers::Offset<comm::datalayer::Reference> vecReferences[] = {
comm::datalayer::CreateReferenceDirect(builder, "readType", "types/mysampleSchema/inertialValue"), };
references2 = builder.CreateVectorOfSortedTables(vecReferences, 1); }
// Set allowed operations
comm::datalayer::AllowedOperationsBuilder allowedOperations(builder);
allowedOperations.add_read(true);
allowedOperations.add_write(false);
allowedOperations.add_create(true);
allowedOperations.add_delete_(false);
auto operations = allowedOperations.Finish();
// Create metadata
comm::datalayer::MetadataBuilder metadata(builder);
metadata.add_description(emptyString);
metadata.add_descriptionUrl(emptyString);
metadata.add_operations(operations);
if (address.compare("myData/myFlatbuffer") == 0) {
metadata.add_references(references); }
else if (address.compare("myData/myFlatbuffer2") == 0) {
metadata.add_references(references2); }
auto metaFinished = metadata.Finish();
builder.Finish(metaFinished);
...
// Create dummy flatbuffer data
flatbuffers::FlatBufferBuilder builder2;
auto actInertialValue2 = mysample::myschema::CreateInertialValue(builder2, 33, -427, 911, 42);
builder2.Finish(actInertialValue2);
comm::datalayer::Variant myFlatbuffer2;
myFlatbuffer2.shareFlatbuffers(builder2);
// Register type of flatbuffer value
// If running on SNAP environment, use $SNAP environment variable for register the bfbs
std::string bfbsPath2 = getenv("SNAP") != nullptr ? getenv("SNAP") : "bfbs";
bfbsPath2 += "/sampleSchema.bfbs";
std::cout << bfbsPath2 << std::endl;
result = myProvider->registerType("types/mysampleSchema/inertialValue", bfbsPath2);
if(STATUS_FAILED(result)) {
std::cout << "Register type 'types/mysampleSchema/inertialValue' failed with: " << result.toString() << std::endl; }
else {
std::cout << "Register type 'types/mysampleSchema/inertialValue' was successful!" << std::endl; }
// Register a node as flatbuffer value
result = myProvider->registerNode("myData/myFlatbuffer2", new MyProviderNode(myFlatbuffer2));
if(STATUS_FAILED(result)) {
std::cout << "Register node 'myData/myFlatbuffer2' failed with: " << result.toString() << std::endl; }
else {
std::cout << "Register node 'myData/myFlatbuffer2' was successful!" << std::endl; }
...
// Unregister type and nodes
myProvider->unregisterType("types/sampleSchema/inertialValue");
myProvider->unregisterType("types/mysampleSchema/inertialValue");
...
09-09-2021 12:07 PM
Hello,
I am interested in making a very similar application to be able to send data to the PLC by Rest API in a single JSON file.
I've started to test the ResgisterNode example but VSCode is giving me an error because it can't find the "SampleSchema_generated.h" library.
How can I fix it, I have no experience with VSCode.
I'm using SDK 1.10 in a virtual machine with Ubuntu 18
Thanks in advance.
09-09-2021 01:39 PM
The "xxx_generated.h" file will be generated by Cmake (code: step number 2 in previous post) just by following the build procedure.
10-13-2021 11:04 AM
I still had problems, but I finally found the error!
strcat shouldn't be used with getenv, because the first arguments gets modified. See std::strcat - cppreference.com
Modifying the lines to something like this resolves the issues when running the app in a snap package:
std::string bfbsPath = getenv("SNAP") != nullptr ? getenv("SNAP") : "bfbs";
bfbsPath += "/sampleSchema.bfbs")
...
std::string bfbsPath2 = getenv("SNAP") != nullptr ? getenv("SNAP") : "bfbs";
bfbsPath2 += "/sampleSchema.bfbs";
11-22-2021 07:57 AM
Thanks for mentioning we will check that and improve our example.