Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ opendaq_setup_project_specific_build_options(${REPO_OPTION_PREFIX})
option(${REPO_OPTION_PREFIX}_ENABLE_EXAMPLE_APP "Enable ${REPO_NAME} example applications" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_TESTS "Enable ${REPO_NAME} testing" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_CLIENT "Enable ${REPO_NAME} client module" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_GENERIC_CLIENT "Enable ${REPO_NAME} client module" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_GENERIC_CLIENT "Enable ${REPO_NAME} generic client module" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_SERVER "Enable ${REPO_NAME} server module" ${PROJECT_IS_TOP_LEVEL})
option(${REPO_OPTION_PREFIX}_ENABLE_SIMPLE_SERVER "Enable ${REPO_NAME} simple server module" ${PROJECT_IS_TOP_LEVEL})
option(OPCUA_ENABLE_ENCRYPTION "Enable OpcUa encryption" OFF)
cmake_dependent_option(OPENDAQ_ENABLE_OPCUA_INTEGRATION_TESTS "Enable ${REPO_NAME} integration testing" ${PROJECT_IS_TOP_LEVEL} "${REPO_OPTION_PREFIX}_ENABLE_TESTS" OFF)

Expand Down
4 changes: 4 additions & 0 deletions modules/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ endif()
if (${REPO_OPTION_PREFIX}_ENABLE_SERVER)
add_subdirectory(opcua_server_module)
endif()

if (${REPO_OPTION_PREFIX}_ENABLE_SIMPLE_SERVER)
add_subdirectory(opcua_simple_server_module)
endif()
9 changes: 9 additions & 0 deletions modules/opcua_simple_server_module/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.10)
opendaq_set_cmake_folder_context(TARGET_FOLDER_NAME)
project(SimpleServerModule VERSION ${${REPO_OPTION_PREFIX}_VERSION} LANGUAGES C CXX)

add_subdirectory(src)

if (${REPO_OPTION_PREFIX}_ENABLE_TESTS)
add_subdirectory(tests)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2022-2025 openDAQ d.o.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once
#include <coretypes/common.h>

#define BEGIN_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE BEGIN_NAMESPACE_OPENDAQ_MODULE(opcua_simple_server_module)
#define END_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE END_NAMESPACE_OPENDAQ_MODULE
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2022-2025 openDAQ d.o.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <opcua_simple_server_module/common.h>

BEGIN_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE

static const char* DAQ_OPCUA_SIMPLE_SERVER_ID = "OpenDAQSimpleOPCUA";
static const char* DAQ_OPCUA_SIMPLE_SERVER_MODULE_NAME = "OpenDAQOPCUASimpleServerModule";
static const char* DAQ_OPCUA_SIMPLE_SERVER_MODULE_ID = "OpenDAQOPCUASimpleServerModule";

static const uint16_t DAQ_OPCUA_SIMPLE_SERVER_DEFAULT_PORT = 4840;
static const char* DAQ_OPCUA_SIMPLE_SERVER_DEFAULT_PATH = "/";


END_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2022-2025 openDAQ d.o.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once
#include <opendaq/module_exports.h>

DECLARE_MODULE_EXPORTS(OpcUaSimpleServerModule)
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2022-2025 openDAQ d.o.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once
#include <coretypes/intfs.h>
#include <opcua_simple_server_module/common.h>
#include <opcuatms_server/tms_server.h>
#include <opendaq/device_ptr.h>
#include <opendaq/server.h>
#include <opendaq/server_impl.h>
#include <opcua_simple_server/simple_server.h>

BEGIN_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE

class OpcUaSimpleServerImpl : public Server
{
public:
explicit OpcUaSimpleServerImpl(const DevicePtr& rootDevice,
const PropertyObjectPtr& config,
const ContextPtr& context);
~OpcUaSimpleServerImpl();
static PropertyObjectPtr createDefaultConfig(const ContextPtr& context);
static ServerTypePtr createType(const ContextPtr& context);
static PropertyObjectPtr populateDefaultConfig(const PropertyObjectPtr& config, const ContextPtr& context);

protected:
PropertyObjectPtr getDiscoveryConfig() override;
void onStopServer() override;
static void populateDefaultConfigFromProvider(const ContextPtr& context, const PropertyObjectPtr& config);

daq::opcua::GenericServer server;
ContextPtr context;
};

OPENDAQ_DECLARE_CLASS_FACTORY_WITH_INTERFACE(
INTERNAL_FACTORY, OpcUaSimpleServer, daq::IServer,
DevicePtr, rootDevice,
PropertyObjectPtr, config,
const ContextPtr&, context
)

END_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2022-2025 openDAQ d.o.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once
#include <opcua_simple_server_module/common.h>
#include <opendaq/module_impl.h>

BEGIN_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE

class OpcUaSimpleServerModule final : public Module
{
public:
OpcUaSimpleServerModule(ContextPtr context);

DictPtr<IString, IServerType> onGetAvailableServerTypes() override;
ServerPtr onCreateServer(const StringPtr& serverType, const PropertyObjectPtr& serverConfig, const DevicePtr& rootDevice) override;

private:
std::mutex sync;
};

END_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE
50 changes: 50 additions & 0 deletions modules/opcua_simple_server_module/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
set(LIB_NAME opcua_simple_server_module)
set(MODULE_HEADERS_DIR ../include/${TARGET_FOLDER_NAME})

set(SRC_Include common.h
constants.h
module_dll.h
opcua_simple_server_module_impl.h
opcua_simple_server_impl.h
)

set(SRC_Srcs module_dll.cpp
opcua_simple_server_module_impl.cpp
opcua_simple_server_impl.cpp
)

opendaq_prepend_include(${TARGET_FOLDER_NAME} SRC_Include)

source_group("module" FILES ${MODULE_HEADERS_DIR}/opcua_simple_server_module_impl.h
${MODULE_HEADERS_DIR}/opcua_simple_server_impl.h
${MODULE_HEADERS_DIR}/module_dll.h
${MODULE_HEADERS_DIR}/common.h
${MODULE_HEADERS_DIR}/constants.h
module_dll.cpp
opcua_simple_server_module_impl.cpp
opcua_simple_server_impl.cpp
)


add_library(${LIB_NAME} SHARED ${SRC_Include}
${SRC_Srcs}
)

add_library(${OPENDAQ_SDK_TARGET_NAMESPACE}::${LIB_NAME} ALIAS ${LIB_NAME})

target_link_libraries(${LIB_NAME} PUBLIC ${OPENDAQ_SDK_TARGET_NAMESPACE}::opendaq
PRIVATE ${OPENDAQ_SDK_TARGET_NAMESPACE}::opcuatms_server
PRIVATE ${OPENDAQ_SDK_TARGET_NAMESPACE}::opcua_simple_server
)

if (MSVC)
target_compile_options(${LIB_NAME} PRIVATE /bigobj)
endif()

target_include_directories(${LIB_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
$<INSTALL_INTERFACE:include>
)

opendaq_set_module_properties(${LIB_NAME} ${PROJECT_VERSION_MAJOR})
opendaq_generate_version_header(${LIB_NAME})
9 changes: 9 additions & 0 deletions modules/opcua_simple_server_module/src/module_dll.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <opcua_simple_server_module/module_dll.h>
#include <opcua_simple_server_module/opcua_simple_server_module_impl.h>

#include <opendaq/module_factory.h>

using namespace daq::modules::opcua_simple_server_module;

DEFINE_MODULE_EXPORTS(OpcUaSimpleServerModule)

112 changes: 112 additions & 0 deletions modules/opcua_simple_server_module/src/opcua_simple_server_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include <opcua_simple_server_module/opcua_simple_server_impl.h>
#include <opcua_simple_server_module/constants.h>
#include <coretypes/impl.h>
#include <coreobjects/property_object_factory.h>
#include <coreobjects/property_factory.h>
#include <opendaq/server_type_factory.h>
#include <opendaq/device_info_factory.h>
#include <opendaq/device_info_internal_ptr.h>

BEGIN_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE
using namespace daq;
using namespace daq::opcua;

OpcUaSimpleServerImpl::OpcUaSimpleServerImpl(const DevicePtr& rootDevice,
const PropertyObjectPtr& config,
const ContextPtr& context)
: Server(DAQ_OPCUA_SIMPLE_SERVER_ID, config, rootDevice, context)
, server(rootDevice, context)
, context(context)
{
const uint16_t port = config.getPropertyValue("Port");

server.setOpcUaPort(port);
server.setOpcUaPath(config.getPropertyValue("Path"));
server.start();
}

OpcUaSimpleServerImpl::~OpcUaSimpleServerImpl()
{
}

void OpcUaSimpleServerImpl::populateDefaultConfigFromProvider(const ContextPtr& context, const PropertyObjectPtr& config)
{
if (!context.assigned())
return;
if (!config.assigned())
return;

auto options = context.getModuleOptions(DAQ_OPCUA_SIMPLE_SERVER_MODULE_ID);
for (const auto& [key, value] : options)
{
if (config.hasProperty(key))
{
config->setPropertyValue(key, value);
}
}
}

PropertyObjectPtr OpcUaSimpleServerImpl::createDefaultConfig(const ContextPtr& context)
{
constexpr Int minPortValue = 0;
constexpr Int maxPortValue = 65535;

auto defaultConfig = PropertyObject();

const auto portProp = IntPropertyBuilder("Port", DAQ_OPCUA_SIMPLE_SERVER_DEFAULT_PORT)
.setMinValue(minPortValue)
.setMaxValue(maxPortValue)
.build();
defaultConfig.addProperty(portProp);

defaultConfig.addProperty(StringProperty("Path", DAQ_OPCUA_SIMPLE_SERVER_DEFAULT_PATH));

populateDefaultConfigFromProvider(context, defaultConfig);
return defaultConfig;
}

PropertyObjectPtr OpcUaSimpleServerImpl::populateDefaultConfig(const PropertyObjectPtr& config, const ContextPtr& context)
{
const auto defConfig = createDefaultConfig(context);
for (const auto& prop : defConfig.getAllProperties())
{
const auto name = prop.getName();
if (config.hasProperty(name))
defConfig.setPropertyValue(name, config.getPropertyValue(name));
}

return defConfig;
}

PropertyObjectPtr OpcUaSimpleServerImpl::getDiscoveryConfig()
{
auto discoveryConfig = PropertyObject();
discoveryConfig.addProperty(StringProperty("ServiceName", "_opcua-tcp._tcp.local."));
discoveryConfig.addProperty(StringProperty("ServiceCap", "OPENDAQ"));
discoveryConfig.addProperty(StringProperty("Path", config.getPropertyValue("Path")));
discoveryConfig.addProperty(IntProperty("Port", config.getPropertyValue("Port")));
discoveryConfig.addProperty(StringProperty("ProtocolVersion", ""));
return discoveryConfig;
}

ServerTypePtr OpcUaSimpleServerImpl::createType(const ContextPtr& context)
{
return ServerType(DAQ_OPCUA_SIMPLE_SERVER_ID,
"openDAQ simple OPC UA server",
"Publishes signal nodes over OPC UA protocol",
OpcUaSimpleServerImpl::createDefaultConfig(context));
}

void OpcUaSimpleServerImpl::onStopServer()
{
server.stop();
}

OPENDAQ_DEFINE_CLASS_FACTORY_WITH_INTERFACE(
INTERNAL_FACTORY, OpcUaSimpleServer, daq::IServer,
daq::DevicePtr, rootDevice,
PropertyObjectPtr, config,
const ContextPtr&, context
)

END_NAMESPACE_OPENDAQ_OPCUA_SIMPLE_SERVER_MODULE
Loading
Loading