Skip to content

Commit

Permalink
Merge Branch Develop into Freeze
Browse files Browse the repository at this point in the history
  • Loading branch information
azoitl authored Dec 18, 2024
2 parents 4519c48 + 2cd4a3f commit de13269
Show file tree
Hide file tree
Showing 67 changed files with 1,177 additions and 440 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/systemtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ jobs:
echo "source-dir=$GITHUB_WORKSPACE" >> "$GITHUB_OUTPUT"
echo "build-dir=$GITHUB_WORKSPACE/build" >> "$GITHUB_OUTPUT"
- name: Install lipcap-dev
# TODO: Enable this and the POWERLINK module back when the CI is fixed: see https://github.com/eclipse-4diac/4diac-forte/issues/287
#- name: Install lipcap-dev
# libpcap-dev is required for the POWERLINK module
# TODO: Put this in 4diac-fortebuildcontainer
run: apt-get update && apt-get install -y libpcap-dev
# run: apt-get update && apt-get install -y libpcap-dev

- name: Configure CMake
run: >
Expand All @@ -51,10 +52,10 @@ jobs:
-DFORTE_MODULE_RT_Events=ON
-DFORTE_MODULE_SIGNALPROCESSING=ON
-DFORTE_MODULE_UTILS=ON
-DFORTE_MODULE_POWERLINK=ON
-DFORTE_TESTS=ON
-DFORTE_SYSTEM_TESTS=ON
-DFORTE_TEST_SANITIZE=ON
# -DFORTE_MODULE_POWERLINK=ON

- name: Build
run: cmake --build ${{ steps.strings.outputs.build-dir }}
Expand Down
8 changes: 7 additions & 1 deletion buildsupport/forte.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ FUNCTION(forte_replace_sourcefile_cpp)
ENDFUNCTION(forte_replace_sourcefile_cpp)

# Add a new possible timer to be created. Pass an extra variable to be used as
# name for the timer handler. If not passed, the default empty string will be used
# name for the timer handler. If not passed, the default string will be used
FUNCTION(forte_add_timerhandler CLASSNAME FILENAME)
set_property(GLOBAL APPEND PROPERTY FORTE_TIMERHANDLER_CLASS ${CLASSNAME})
set_property(GLOBAL APPEND PROPERTY FORTE_TIMERHANDLER_FILENAME "${FILENAME}.h")
Expand Down Expand Up @@ -242,6 +242,12 @@ MACRO(forte_add_handler CLASSNAME FILENAME)
set_property(GLOBAL APPEND PROPERTY FORTE_HANDLER_FILENAME "${FILENAME}.h")
ENDMACRO(forte_add_handler)

MACRO(forte_add_ecet CLASSNAME FILENAME ECET_NAME)
set_property(GLOBAL APPEND PROPERTY FORTE_ECET_CLASS ${CLASSNAME})
set_property(GLOBAL APPEND PROPERTY FORTE_ECET_FILENAME "${FILENAME}.h")
set_property(GLOBAL APPEND PROPERTY FORTE_ECET_NAME "${ECET_NAME}")
ENDMACRO(forte_add_ecet)

MACRO(forte_add_startup_hook FUNCTION_NAME)
set_property(GLOBAL APPEND PROPERTY FORTE_STARTUP_HOOK_FUNCTIONS ${FUNCTION_NAME})
ENDMACRO(forte_add_startup_hook)
Expand Down
41 changes: 41 additions & 0 deletions dependencies.spdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## This file conforms to ISO/IEC 5962:2021 a.k.a. SPDX-2.2.1 (lite variant)
SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Eclipse-4diac-FORTE-SBOM
DocumentNamespace: https://eclipse.dev/4diac/
Creator: Organization: Eclipse-4diac
Created: 2024-11-21T14:43:43Z
CreatorComment: <text>This file documents optional external dependencies of 4diac FORTE in a standardised machine-readable format</text>

## This package
#####################################
PackageName: 4diac-FORTE
SPDXID: SPDXRef-4diac-FORTE
PackageComment: <text>4diac FORTE source code</text>
ExternalRef: PACKAGE-MANAGER purl pkg:github/eclipse-4diac/4diac-forte@develop
PackageVersion: develop
PackageSupplier: Organization: Eclipse-4diac
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-4diac-FORTE
PackageDownloadLocation: https://github.com/eclipse-4diac/4diac-forte/archive/develop.zip
FilesAnalyzed: false
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION

## Optional dependencies
#####################################
PackageName: open62541
SPDXID: SPDXRef-open62541
PackageComment: <text>OPC-UA support library</text>
ExternalRef: PACKAGE-MANAGER purl pkg:github/open62541/[email protected]
PackageVersion: 1.4.7
PackageSupplier: Organization: open62541
Relationship: SPDXRef-open62541 OPTIONAL_DEPENDENCY_OF SPDXRef-4diac-FORTE
PackageDownloadLocation: https://github.com/open62541/open62541/archive/refs/tags/v1.4.7.zip
PackageChecksum: SHA256: 598889ae4bdc468d39c5c961ba76c648747b64337a9d0c0ef07b032c4819dea8
FilesAnalyzed: false
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION

1 change: 1 addition & 0 deletions setup_zephyr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ if [ -d "$forte_bin_dir" ]; then
-DFORTE_SUPPORT_BOOT_FILE=ON \
-DFORTE_BUILD_EXECUTABLE=OFF \
-DFORTE_BUILD_STATIC_LIBRARY=ON \
-DFORTE_C_INTERFACE=ON \
-DFORTE_MODULE_CONVERT=ON \
-DFORTE_MODULE_IEC61131=ON \
-DFORTE_IO=ON \
Expand Down
36 changes: 36 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,42 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/arch/timerHandlerFactory.cpp.in ${CMA
forte_replacefile_if_changed(${CMAKE_BINARY_DIR}/arch/timerHandlerFactory_new.cpp ${CMAKE_BINARY_DIR}/arch/timerHandlerFactory.cpp)
file(REMOVE ${CMAKE_BINARY_DIR}/arch/timerHandlerFactory_new.cpp)

#############################################################################
# Configure ECETs
#############################################################################

GET_PROPERTY(ECET_CLASS GLOBAL PROPERTY FORTE_ECET_CLASS)
GET_PROPERTY(ECET_FILENAME GLOBAL PROPERTY FORTE_ECET_FILENAME)
GET_PROPERTY(ECET_NAME GLOBAL PROPERTY FORTE_ECET_NAME)

LIST(LENGTH ECET_CLASS ECET_CLASS_LEN)
math(EXPR ECET_CLASS_LEN ${ECET_CLASS_LEN}-1)

SET(ECET_INCLUDE "")
SET(ECET_CREATE "")
SET(ECET_ENUM "")


FOREACH(POS RANGE ${ECET_CLASS_LEN})
LIST(GET ECET_CLASS ${POS} CLASS)
LIST(GET ECET_FILENAME ${POS} FILENAME)
LIST(GET ECET_NAME ${POS} NAME_)

SET(ECET_INCLUDE "${ECET_INCLUDE}#include \"${FILENAME}\"\n")

SET(ECET_ENUM "${ECET_ENUM}\n ${NAME_},")

SET(ECET_CREATE "${ECET_CREATE} if(ecetToCreate == AvailableEcets::${NAME_}) return new ${CLASS}();\n")
math(EXPR ECET_ID ${ECET_ID}+1)
ENDFOREACH(POS)

CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/core/ecetFactory.cpp.in ${CMAKE_BINARY_DIR}/core/ecetFactory_new.cpp)
forte_replacefile_if_changed(${CMAKE_BINARY_DIR}/core/ecetFactory_new.cpp ${CMAKE_BINARY_DIR}/core/ecetFactory.cpp)
file(REMOVE ${CMAKE_BINARY_DIR}/core/ecetFactory_new.cpp)

CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/core/ecetFactory.h.in ${CMAKE_BINARY_DIR}/core/ecetFactory_new.h)
forte_replacefile_if_changed(${CMAKE_BINARY_DIR}/core/ecetFactory_new.h ${CMAKE_BINARY_DIR}/core/ecetFactory.h)
file(REMOVE ${CMAKE_BINARY_DIR}/core/ecetFactory_new.h)
#############################################################################
# Configure startuphook
#############################################################################
Expand Down
14 changes: 7 additions & 7 deletions src/arch/zephyr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ ExternalProject_Add(forte
-DFORTE_SUPPORT_BOOT_FILE=ON
-DFORTE_BUILD_EXECUTABLE=OFF
-DFORTE_BUILD_STATIC_LIBRARY=ON
-DFORTE_C_INTERFACE=ON
-DFORTE_MODULE_CONVERT=ON
-DFORTE_MODULE_IEC61131=ON
-DFORTE_IO=ON
Expand All @@ -53,23 +54,23 @@ ExternalProject_Add(forte
-DFORTE_EXTERNAL_MODULES_DIRECTORY=${forte_src_dir}/ExportedFBs
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DFORTE_LOGLEVEL=LOGINFO
-DFORTE_LOGLEVEL=NOLOG
-DCMAKE_BUILD_TYPE=MINSIZEREL
-DCMAKE_C_FLAGS_DEBUG="-g"
-DCMAKE_CXX_FLAGS=${external_project_cxxflags}
-DFORTE_SOURCE_DIR=${forte_src_dir}
../../
BUILD_COMMAND
ninja
BUILD_BYPRODUCTS ${FORTE_LIB_DIR}/libforte-static.a
BUILD_BYPRODUCTS ${FORTE_LIB_DIR}/libforte-c-static.a
INSTALL_COMMAND ""
)
add_dependencies(forte zephyr_interface)
add_library(forte_lib STATIC IMPORTED GLOBAL)
add_dependencies(forte_lib forte)
set_target_properties(forte_lib PROPERTIES IMPORTED_LOCATION ${FORTE_LIB_DIR}/libforte-static.a)
set_target_properties(forte_lib PROPERTIES IMPORTED_LOCATION ${FORTE_LIB_DIR}/libforte-c-static.a)
target_include_directories(forte_lib INTERFACE ${forte_src_dir}/src/arch)
```

Expand Down Expand Up @@ -97,7 +98,6 @@ CONFIG_CPP=y
CONFIG_STD_CPP20=y
CONFIG_REQUIRES_FULL_LIBCPP=y
CONFIG_COMPILER_OPT="-Werror"
CONFIG_POSIX_CLOCK=y
# Dynamic thread creation for 4diac FORTE
CONFIG_DYNAMIC_THREAD=y
Expand All @@ -110,6 +110,8 @@ CONFIG_HEAP_MEM_POOL_SIZE=64000
# TCP/IP networking for 4diac FORTE
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_POSIX_API=y
CONFIG_NET_ARP=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
Expand All @@ -121,10 +123,8 @@ CONFIG_NET_IPV4=y
CONFIG_NET_MAX_CONN=20
CONFIG_NET_CONTEXT_RCVTIMEO=y
CONFIG_POSIX_MAX_FDS=12
CONFIG_ZVFS_OPEN_MAX=12
CONFIG_NET_MAX_CONTEXTS=16
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y # unset if CONFIG_POSIX_API=y
CONFIG_NET_PROMISCUOUS_MODE=y
# CONFIG_ETH_MCUX_PROMISCUOUS_MODE=y # required by NXP MCUX SOCs
Expand Down
2 changes: 1 addition & 1 deletion src/arch/zephyr/forte_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void CZephyrThread::threadFunction(void* arg1, void* arg2, void* arg3) {
forte::arch::CThreadBase<k_tid_t, nullptr, CZephyrThread>::TThreadHandleType CZephyrThread::createThread(long paStackSize) {
if (thread == nullptr) return nullptr;
auto thread_id = k_thread_create(thread, stack, paStackSize, threadFunction, this, NULL, NULL, 10, K_FP_REGS, K_NO_WAIT);
k_thread_name_set(thread_id, "forte_thread");
if (thread_id) k_thread_name_set(thread_id, "forte_thread");
return thread_id;
}

Expand Down
2 changes: 1 addition & 1 deletion src/arch/zephyr/sockhand.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "devlog.h"

#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_if.h>
#include <zephyr/posix/arpa/inet.h>
#include <zephyr/net/socket.h>
#include <zephyr/kernel.h>
Expand Down
5 changes: 4 additions & 1 deletion src/arch/zephyr/zephyrtiha.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CZephyrTimerHandler::CZephyrTimerHandler(CDeviceExecution& paDeviceExecution) :
return;
}
thread_id = k_thread_create(thread, stack, stackSize, thread_fn, this, NULL, NULL, 1, K_FP_REGS, K_FOREVER);
k_thread_name_set(thread_id, "forte_tiha");
if (thread_id) k_thread_name_set(thread_id, "forte_tiha");
}

CZephyrTimerHandler::~CZephyrTimerHandler() {
Expand All @@ -48,6 +48,9 @@ CZephyrTimerHandler::~CZephyrTimerHandler() {
}

void CZephyrTimerHandler::enableHandler() {
if (thread == nullptr) {
return;
}
const auto period = K_NSEC(forte::core::constants::cNanosecondsPerSecond / getTicksPerSecond());
k_timer_start(&timer, period, period);
k_thread_start(thread_id);
Expand Down
2 changes: 2 additions & 0 deletions src/com/opc_ua/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ if (FORTE_COM_OPC_UA)

add_subdirectory(FBs)
add_subdirectory(types)
add_subdirectory(detail)


if(FORTE_COM_OPC_UA_ENCRYPTION)
SET(FORTE_COM_OPC_UA_ENCRYPTION_INCLUDE_DIR "" CACHE STRING "ABSOLUTE path to encryption headers")
Expand Down
4 changes: 4 additions & 0 deletions src/com/opc_ua/detail/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

if(FORTE_COM_OPC_UA_MULTICAST)
forte_add_sourcefile_hcpp(lds_me_handler)
endif(FORTE_COM_OPC_UA_MULTICAST)
100 changes: 100 additions & 0 deletions src/com/opc_ua/detail/lds_me_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@

#include "lds_me_handler.h"

#include "devlog.h"

using namespace forte::com::opc_ua::detail;

LdsMeHandler::LdsMeHandler(UA_Server& paUaServer) : mUaServer{paUaServer} {
UA_Server_setServerOnNetworkCallback(&mUaServer, serverOnNetworkCallback, this);
}

LdsMeHandler::~LdsMeHandler() {
for(const auto& registeredServer : mRegisteredServers){
deregisterDiscoveryServer(registeredServer.mString);
}
UA_Server_setServerOnNetworkCallback(&mUaServer, nullptr, nullptr);
}

void LdsMeHandler::configureServer(UA_ServerConfig& paUaServerConfig, const std::string& paServerName) {
UA_String_clear(&paUaServerConfig.mdnsConfig.mdnsServerName);
paUaServerConfig.mdnsConfig.mdnsServerName = UA_String_fromChars(paServerName.c_str());
// Enable the mDNS announce and response functionality
paUaServerConfig.mdnsEnabled = true;
}

void LdsMeHandler::serverOnNetworkCallback(const UA_ServerOnNetwork* paServerOnNetwork, UA_Boolean paIsServerAnnounce, UA_Boolean paIsTxtReceived, void* paData) {

if(!paIsTxtReceived) {
return; // we wait until the corresponding TXT record is announced.
}

DEVLOG_DEBUG("[OPC UA LDS ME]: mDNS %s '%.*s' with url '%.*s'\n", paIsServerAnnounce ? "announce" : "remove", paServerOnNetwork->serverName.length,
paServerOnNetwork->serverName.data, paServerOnNetwork->discoveryUrl.length, paServerOnNetwork->discoveryUrl.data);

// check if server is LDS
bool isServerLDS = false;

UA_StringRAII ldsStr("LDS");
for(unsigned int i = 0; i < paServerOnNetwork->serverCapabilitiesSize; i++) {
if(UA_String_equal(&paServerOnNetwork->serverCapabilities[i], &ldsStr.mString)) {
isServerLDS = true;
break;
}
}

// skip non-LDS servers
if(!isServerLDS) {
return;
}

auto handler = static_cast<LdsMeHandler*>(paData);

auto foundDiscoveryUrl = handler->mRegisteredServers.end();
for(auto iter = handler->mRegisteredServers.begin(); iter != handler->mRegisteredServers.end(); iter++) {
if(UA_String_equal(&paServerOnNetwork->discoveryUrl, &iter->mString)) {
foundDiscoveryUrl = iter;
break;
}
}

// if a new server is being announced
if(paIsServerAnnounce && foundDiscoveryUrl == handler->mRegisteredServers.end()) {
if(handler->registerDiscoveryServer(paServerOnNetwork->discoveryUrl)){
handler->mRegisteredServers.emplace_back(paServerOnNetwork->discoveryUrl);
}
// if a known server is being un-announced
} else if(!paIsServerAnnounce && foundDiscoveryUrl != handler->mRegisteredServers.end()) {
handler->deregisterDiscoveryServer(foundDiscoveryUrl->mString);
handler->mRegisteredServers.erase(foundDiscoveryUrl);
}
}

bool LdsMeHandler::registerDiscoveryServer(const UA_String& paDiscoveryUrl) {

UA_ClientConfig clientConfig;
memset(&clientConfig, 0, sizeof(UA_ClientConfig));
UA_ClientConfig_setDefault(&clientConfig);
auto retVal = UA_Server_registerDiscovery(&mUaServer, &clientConfig, paDiscoveryUrl, UA_STRING_NULL);
if( UA_STATUSCODE_GOOD != retVal) {
DEVLOG_ERROR("[OPC UA LDSME]: Could not register with LDS. Error: %s\n", UA_StatusCode_name(retVal));
return false;
}
DEVLOG_INFO("[OPC UA LDSME]: Registered to LDS '%.*s'\n", paDiscoveryUrl.length, paDiscoveryUrl.data);
return true;
}

void LdsMeHandler::deregisterDiscoveryServer(const UA_String& paDiscoveryUrl) {
UA_ClientConfig clientConfig;
memset(&clientConfig, 0, sizeof(UA_ClientConfig));
UA_ClientConfig_setDefault(&clientConfig);

auto retVal = UA_Server_deregisterDiscovery(&mUaServer, &clientConfig, paDiscoveryUrl);
// if unregister fails, we don't do anything else
if( UA_STATUSCODE_GOOD != retVal) {
DEVLOG_ERROR("[OPC UA LDSME]: Could not deregister with LDS. Error: %s\n", UA_StatusCode_name(retVal));
return;
}

DEVLOG_INFO("[OPC UA LDSME]: Unregistered from LDS '%.*s'\n", paDiscoveryUrl.length, paDiscoveryUrl.data);
}
Loading

0 comments on commit de13269

Please sign in to comment.