From 326af6a48c97f31e2c3ab67d33185a862c2d0338 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 08:17:35 +0200 Subject: [PATCH 01/29] Expose analog inputs of analog expansion modules via OPC UA. --- examples/opcua_server/opcua_server.ino | 18 +++++++++++ src/expansion/AnalogExpansion.cpp | 43 ++++++++++++++++++++++++++ src/expansion/AnalogExpansion.h | 9 ++++++ 3 files changed, 70 insertions(+) create mode 100644 src/expansion/AnalogExpansion.cpp diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 3016e16..b3734fd 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -258,6 +258,24 @@ void setup() else if (exp_type == EXPANSION_OPTA_ANALOG) { auto const exp_analog = opta_expansion_manager_opcua->create_analog_expansion(i); + + for(int a = 0; a < OA_AN_CHANNELS_NUM; a++) + { + /* Configure analog expansion module analog channels as analog inputs. */ + AnalogExpansion::beginChannelAsAdc(OptaController, + i, /* expansion module number */ + a, /* analog channel of expansion module */ + OA_VOLTAGE_ADC, /* ADC type */ + true, /* enable pull down */ + false, /* disable rejection */ + false, /* disable diagnostic */ + 0); /* disable averaging */ + + /* Expose analog inputs as readable OPC UA properties. */ + char analog_in_name[32] = {0}; + snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", a + 1); + exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->analogRead(a); }); + } } } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp new file mode 100644 index 0000000..3185a51 --- /dev/null +++ b/src/expansion/AnalogExpansion.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "AnalogExpansion.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +AnalogInputManager::SharedPtr AnalogExpansion::analog_input_mgr() +{ + if (!_analog_input_mgr) + { + _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); + if (!_analog_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::analog_input_mgr: AnalogInputManager::create(...) failed."); + } + + return _analog_input_mgr; +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 2cacc67..544e862 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -17,6 +17,8 @@ #include +#include "../io/analog/AnalogInputManager.h" + /************************************************************************************** * NAMESPACE **************************************************************************************/ @@ -56,6 +58,13 @@ class AnalogExpansion : public Expansion char * model_name) : Expansion(server, parent_node_id, display_name, node_name, model_name) { } + + + AnalogInputManager::SharedPtr analog_input_mgr(); + + +private: + AnalogInputManager::SharedPtr _analog_input_mgr; }; /************************************************************************************** From f9d3c7517c3c3faf99e5db781406182ef15b1dd3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 08:35:10 +0200 Subject: [PATCH 02/29] Limit support for expansion modules to 2 (can't afford more due to RAM). --- examples/opcua_server/opcua_server.ino | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index b3734fd..5988e2e 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -20,6 +20,8 @@ * CONSTANTS **************************************************************************************/ +static uint8_t const OPCUA_MAX_OPTA_EXPANSION_NUM = 2; + #if USE_MODBUS_SENSOR_MD02 static unsigned int const MODBUS_BAUDRATE = 9600; static float const MODBUS_BIT_DURATION = 1.f / MODBUS_BAUDRATE; @@ -206,7 +208,7 @@ void setup() } /* Check availability of expansion modules. */ - uint8_t const opta_expansion_num = OptaController.getExpansionNum(); + uint8_t opta_expansion_num = OptaController.getExpansionNum(); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "OptaController %d expansion modules detected.", opta_expansion_num); for(uint8_t i = 0; i < opta_expansion_num; i++) UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Expansion %d: type = %d (\"%16s\"), I2C address= 0x%02X", @@ -221,6 +223,16 @@ void setup() } } + /* Limit the maximum amount of concurrently supported OPC UA expansion + * modules, as exposing expansion modules via OPC UA is a RAM hungry affair, + * and we are fairly limited in terms of available RAM. + */ + if (opta_expansion_num > OPCUA_MAX_OPTA_EXPANSION_NUM) + { + UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Enabling only %d expansion modules (RAM constraints).", OPCUA_MAX_OPTA_EXPANSION_NUM); + opta_expansion_num = OPCUA_MAX_OPTA_EXPANSION_NUM; + } + /* Expose Arduino Opta expansion module IO via OPC/UA. */ for(uint8_t i = 0; i < opta_expansion_num; i++) { From 5023c47df5b46d4abf588eeacfd74df55c39e03c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 08:37:32 +0200 Subject: [PATCH 03/29] Transfer constant from sketch to library. --- examples/opcua_server/opcua_server.ino | 2 -- src/Arduino_open62541.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 5988e2e..1b3747a 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -20,8 +20,6 @@ * CONSTANTS **************************************************************************************/ -static uint8_t const OPCUA_MAX_OPTA_EXPANSION_NUM = 2; - #if USE_MODBUS_SENSOR_MD02 static unsigned int const MODBUS_BAUDRATE = 9600; static float const MODBUS_BIT_DURATION = 1.f / MODBUS_BAUDRATE; diff --git a/src/Arduino_open62541.h b/src/Arduino_open62541.h index 9e1aaae..7818c8e 100644 --- a/src/Arduino_open62541.h +++ b/src/Arduino_open62541.h @@ -32,3 +32,5 @@ #if !defined(ARDUINO_OPTA) # error "This library does only support Arduino Opta" #endif + +#define OPCUA_MAX_OPTA_EXPANSION_NUM (2u) From 1a17e0e9b4ff506fa54a88d587c6e361a44aeec3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 08:39:02 +0200 Subject: [PATCH 04/29] Documenting source of limitation of supported expansion modules. --- src/Arduino_open62541.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Arduino_open62541.h b/src/Arduino_open62541.h index 7818c8e..1d0f020 100644 --- a/src/Arduino_open62541.h +++ b/src/Arduino_open62541.h @@ -33,4 +33,8 @@ # error "This library does only support Arduino Opta" #endif +/* Note: exposing properties via OPC UA is extremely + * RAM hungry. We therefore need to limit the number + * of supported Opta expansion modules via OPC UA. + */ #define OPCUA_MAX_OPTA_EXPANSION_NUM (2u) From 00e1ec9b663a6e027a730e44b3a381cb612f9ad6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 08:43:15 +0200 Subject: [PATCH 05/29] Dedicating 320 kBytes for OPC UA heap allows for two expansion modules. Anything more and the general application heap overwrites our dededicated opcua heap, resuling in application crash. Anything less and we can not sustain two expansion modules. --- examples/opcua_server/opcua_server.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 1b3747a..98e5c68 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -39,7 +39,7 @@ static size_t const OPC_UA_SERVER_THREAD_STACK_SIZE = 16*1024UL; template struct alignas(uint32_t) OPC_UA_STACK final : public std::array {}; static OPC_UA_STACK OPC_UA_SERVER_THREAD_STACK; -static size_t const OPC_UA_SERVER_THREAD_HEAP_SIZE = (256+128)*1024UL; +static size_t const OPC_UA_SERVER_THREAD_HEAP_SIZE = 320*1024UL; template struct alignas(O1HEAP_ALIGNMENT) OPC_UA_HEAP final : public std::array {}; static OPC_UA_HEAP OPC_UA_SERVER_THREAD_HEAP; From 30701aeec3551e95228b82d16204c44b370922a4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 09:03:32 +0200 Subject: [PATCH 06/29] Fix: periodically call "updateAnalogInputs" in order to obtain the latest input value. --- examples/opcua_server/opcua_server.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 98e5c68..07abb40 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -395,6 +395,8 @@ void loop() reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); else if (exp_type == EXPANSION_OPTA_DIGITAL_STS) reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); + else if (exp_type == EXPANSION_OPTA_ANALOG) + reinterpret_cast(OptaController.getExpansionPtr(i))->updateAnalogInputs(); } /* Toggle main LED signalling progress. */ From 5f461f79eced314ff9a4c5834027fbd37a0895d4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 09:08:11 +0200 Subject: [PATCH 07/29] There is no need to update connected expansion modules which we are currently not exposing via OPC UA. --- examples/opcua_server/opcua_server.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 07abb40..5356022 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -387,7 +387,10 @@ void loop() OptaController.update(); /* Determine the number of expansion boards available and call update on them. */ - uint8_t const opta_expansion_num = OptaController.getExpansionNum(); + uint8_t opta_expansion_num = OptaController.getExpansionNum(); + if (opta_expansion_num > OPCUA_MAX_OPTA_EXPANSION_NUM) + opta_expansion_num = OPCUA_MAX_OPTA_EXPANSION_NUM; + /* Periodically call their respective update methods. */ for(uint8_t i = 0; i < opta_expansion_num; i++) { ExpansionType_t const exp_type = OptaController.getExpansionType(i); From d5a2ff433fb8940b30a23782f207684d3d619415 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 09:22:27 +0200 Subject: [PATCH 08/29] Fix: do not use raw ADC reading but already converted pin voltage. Also no need to periodically update anymore, as we are doing the update right when reading the OPC UA property. --- examples/opcua_server/opcua_server.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 5356022..42a2d78 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -284,7 +284,7 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_in_name[32] = {0}; snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", a + 1); - exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->analogRead(a); }); + exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); }); } } } @@ -398,8 +398,6 @@ void loop() reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); else if (exp_type == EXPANSION_OPTA_DIGITAL_STS) reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); - else if (exp_type == EXPANSION_OPTA_ANALOG) - reinterpret_cast(OptaController.getExpansionPtr(i))->updateAnalogInputs(); } /* Toggle main LED signalling progress. */ From 4033b0b7eaf1a5c13cad8d6248da4e4941923511 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 26 Aug 2024 09:38:57 +0200 Subject: [PATCH 09/29] Enable control of exposed LEDs on analog expansion module. --- examples/opcua_server/opcua_server.ino | 17 +++++++++++++++++ src/expansion/AnalogExpansion.cpp | 12 ++++++++++++ src/expansion/AnalogExpansion.h | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 42a2d78..b47149f 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -286,6 +286,23 @@ void setup() snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", a + 1); exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); }); } + + /* Configure controllable LEDs of analog expansion module. */ + for (int l = 0; l < OA_LED_NUM; l++) + { + char led_name[32] = {0}; + snprintf(led_name, sizeof(led_name), "LED%d", l + 1); + exp_analog->led_mgr()->add_led_output(opc_ua_server, + led_name, + [i, l](bool const value) + { + AnalogExpansion * ana_exp_ptr = reinterpret_cast(OptaController.getExpansionPtr(i)); + if (value) + ana_exp_ptr->switchLedOn(l); + else + ana_exp_ptr->switchLedOff(l); + }); + } } } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 3185a51..d74b88f 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -36,6 +36,18 @@ AnalogInputManager::SharedPtr AnalogExpansion::analog_input_mgr() return _analog_input_mgr; } +LedManager::SharedPtr AnalogExpansion::led_mgr() +{ + if (!_led_mgr) + { + _led_mgr = opcua::LedManager::create(_server, _node_id); + if (!_led_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::led_mgr: LedManager::create(...) failed."); + } + + return _led_mgr; +} + /************************************************************************************** * NAMESPACE **************************************************************************************/ diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 544e862..bd89aa3 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -17,6 +17,7 @@ #include +#include "../io/led/LedManager.h" #include "../io/analog/AnalogInputManager.h" /************************************************************************************** @@ -61,10 +62,13 @@ class AnalogExpansion : public Expansion AnalogInputManager::SharedPtr analog_input_mgr(); + LedManager::SharedPtr led_mgr(); + private: AnalogInputManager::SharedPtr _analog_input_mgr; + LedManager::SharedPtr _led_mgr; }; /************************************************************************************** From 97151610a7207d2d3cd2ac157d0da29d5ecd0668 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Aug 2024 10:19:02 +0200 Subject: [PATCH 10/29] Basic implementation for controlling the analog output. --- examples/opcua_server/opcua_server.ino | 19 +++- src/expansion/AnalogExpansion.cpp | 12 +++ src/expansion/AnalogExpansion.h | 7 +- src/io/analog/AnalogOutput.cpp | 129 +++++++++++++++++++++++++ src/io/analog/AnalogOutput.h | 59 +++++++++++ src/io/analog/AnalogOutputManager.cpp | 84 ++++++++++++++++ src/io/analog/AnalogOutputManager.h | 57 +++++++++++ 7 files changed, 364 insertions(+), 3 deletions(-) create mode 100644 src/io/analog/AnalogOutput.cpp create mode 100644 src/io/analog/AnalogOutput.h create mode 100644 src/io/analog/AnalogOutputManager.cpp create mode 100644 src/io/analog/AnalogOutputManager.h diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index b47149f..050dc5f 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -269,7 +269,7 @@ void setup() { auto const exp_analog = opta_expansion_manager_opcua->create_analog_expansion(i); - for(int a = 0; a < OA_AN_CHANNELS_NUM; a++) + for(int a = OA_CH_0; a <= OA_CH_5; a++) { /* Configure analog expansion module analog channels as analog inputs. */ AnalogExpansion::beginChannelAsAdc(OptaController, @@ -287,6 +287,23 @@ void setup() exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); }); } + for(int a = OA_CH_6; a <= OA_CH_7; a++) + { + /* Configure analog expansion module analog channels as analog outputs. */ + AnalogExpansion::beginChannelAsDac(OptaController, + i, /* expansion module number */ + a, /* analog channel of expansion module */ + OA_VOLTAGE_DAC, /* DAC type */ + true, /* limit current */ + false, /* disable slew rate */ + OA_SLEW_RATE_0); + + /* Expose analog inputs as readable OPC UA properties. */ + char analog_out_name[32] = {0}; + snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output I%d", a + 1); + exp_analog->analog_output_mgr()->add_analog_output(opc_ua_server, analog_out_name, [i, a](float const voltage) { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); }); + } + /* Configure controllable LEDs of analog expansion module. */ for (int l = 0; l < OA_LED_NUM; l++) { diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index d74b88f..d8122c9 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -36,6 +36,18 @@ AnalogInputManager::SharedPtr AnalogExpansion::analog_input_mgr() return _analog_input_mgr; } +AnalogOutputManager::SharedPtr AnalogExpansion::analog_output_mgr() +{ + if (!_analog_output_mgr) + { + _analog_output_mgr = opcua::AnalogOutputManager::create(_server, _node_id); + if (!_analog_output_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::analog_output_mgr: AnalogOutputManager::create(...) failed."); + } + + return _analog_output_mgr; +} + LedManager::SharedPtr AnalogExpansion::led_mgr() { if (!_led_mgr) diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index bd89aa3..93e8632 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -19,6 +19,7 @@ #include "../io/led/LedManager.h" #include "../io/analog/AnalogInputManager.h" +#include "../io/analog/AnalogOutputManager.h" /************************************************************************************** * NAMESPACE @@ -61,13 +62,15 @@ class AnalogExpansion : public Expansion { } - AnalogInputManager::SharedPtr analog_input_mgr(); - LedManager::SharedPtr led_mgr(); + AnalogInputManager::SharedPtr analog_input_mgr(); + AnalogOutputManager::SharedPtr analog_output_mgr(); + LedManager::SharedPtr led_mgr(); private: AnalogInputManager::SharedPtr _analog_input_mgr; + AnalogOutputManager::SharedPtr _analog_output_mgr; LedManager::SharedPtr _led_mgr; }; diff --git a/src/io/analog/AnalogOutput.cpp b/src/io/analog/AnalogOutput.cpp new file mode 100644 index 0000000..5f12858 --- /dev/null +++ b/src/io/analog/AnalogOutput.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "AnalogOutput.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * FUNCTION DEFINITION + **************************************************************************************/ + +static void analog_output_on_write_request(UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + AnalogOutput * this_ptr = reinterpret_cast(nodeContext); + bool const voltage = *(UA_Float *)(data->value.data); + this_ptr->onWriteRequest(server, nodeid, voltage); +} + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +AnalogOutput::AnalogOutput(UA_NodeId const & node_id, OnWriteRequestFunc const on_write_request) +: _node_id{node_id} +, _on_write_request{on_write_request} +{ + +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +AnalogOutput::SharedPtr AnalogOutput::create(UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnWriteRequestFunc const on_write_request) +{ + UA_StatusCode rc = UA_STATUSCODE_GOOD; + + UA_VariableAttributes analog_output_value_attr = UA_VariableAttributes_default; + + UA_Boolean analog_output_value = 0.; + UA_Variant_setScalar(&analog_output_value_attr.value, &analog_output_value, &UA_TYPES[UA_TYPES_FLOAT]); + + analog_output_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); + analog_output_value_attr.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId; + analog_output_value_attr.accessLevel = + UA_ACCESSLEVELMASK_READ | + UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_STATUSWRITE | + UA_ACCESSLEVELMASK_TIMESTAMPWRITE; /* Status and timestamp write access necessary for opcua-client. */ + + UA_NodeId node_id; + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "Value"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + analog_output_value_attr, + NULL, + &node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "AnalogOutput::create: UA_Server_addVariableNode(...) failed with %s", UA_StatusCode_name(rc)); + return nullptr; + } + + /* Create an instance of AnalogOutput here. */ + auto const instance_ptr = std::make_shared(node_id, on_write_request); + + rc = UA_Server_setNodeContext(server, node_id, reinterpret_cast(instance_ptr.get())); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "AnalogOutput::create: UA_Server_setNodeContext(...) failed with %s", + UA_StatusCode_name(rc)); + return nullptr; + } + + UA_ValueCallback callback; + callback.onRead = NULL; + callback.onWrite = analog_output_on_write_request; + rc = UA_Server_setVariableNode_valueCallback(server, node_id, callback); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "AnalogOutput::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", + UA_StatusCode_name(rc)); + return nullptr; + } + + return instance_ptr; +} + +void AnalogOutput::onWriteRequest(UA_Server * server, UA_NodeId const * node_id, float const voltage) +{ + /* Some debug output. */ + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogOutput::onWriteRequest: voltage = %0.2f", voltage); + _on_write_request(voltage); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/analog/AnalogOutput.h b/src/io/analog/AnalogOutput.h new file mode 100644 index 0000000..6402e1d --- /dev/null +++ b/src/io/analog/AnalogOutput.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "../../open62541.h" + +#include +#include + +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class AnalogOutput +{ +public: + typedef std::shared_ptr SharedPtr; + typedef std::function OnWriteRequestFunc; + + static SharedPtr create(UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnWriteRequestFunc const on_write_request); + + AnalogOutput(UA_NodeId const & node_id, OnWriteRequestFunc const on_write_request); + + void onWriteRequest(UA_Server * server, UA_NodeId const * node_id, float const voltage); + + +private: + UA_NodeId _node_id; + OnWriteRequestFunc _on_write_request; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/analog/AnalogOutputManager.cpp b/src/io/analog/AnalogOutputManager.cpp new file mode 100644 index 0000000..628c455 --- /dev/null +++ b/src/io/analog/AnalogOutputManager.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "AnalogOutputManager.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +AnalogOutputManager::AnalogOutputManager(UA_NodeId const & node_id) +: _node_id{node_id} +{ + /* Nothing happens here. */ +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +AnalogOutputManager::SharedPtr AnalogOutputManager::create(UA_Server * server, UA_NodeId const parent_node_id) +{ + UA_StatusCode rc = UA_STATUSCODE_GOOD; + + UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Analog Outputs"); + UA_NodeId node_id; + rc = UA_Server_addObjectNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_QUALIFIEDNAME(1, "AnalogOutputs"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), + oAttr, + NULL, + &node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "AnalogOutputManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + return nullptr; + } + + auto const instance_ptr = std::make_shared(node_id); + return instance_ptr; +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +void AnalogOutputManager::add_analog_output(UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func) +{ + auto const analog_output = AnalogOutput::create(server, _node_id, display_name, on_write_request_func); + if (!analog_output) { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogOutputManager::add_analog_output: AnalogOutput::create(...) failed: returned nullptr"); + return; + } + _analog_output_list.push_back(analog_output); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/analog/AnalogOutputManager.h b/src/io/analog/AnalogOutputManager.h new file mode 100644 index 0000000..5268a0c --- /dev/null +++ b/src/io/analog/AnalogOutputManager.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "../../open62541.h" + +#include +#include + +#include "AnalogOutput.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class AnalogOutputManager +{ +public: + typedef std::shared_ptr SharedPtr; + + static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); + + AnalogOutputManager(UA_NodeId const & node_id); + + void add_analog_output(UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func); + + +private: + UA_NodeId _node_id; + std::list _analog_output_list; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ From f5a74e37e43cb9476dbe0b8cbb0d3c60b2ec13ad Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Aug 2024 10:22:33 +0200 Subject: [PATCH 11/29] Fix erroneous case to boolean (most be float). --- src/io/analog/AnalogOutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/analog/AnalogOutput.cpp b/src/io/analog/AnalogOutput.cpp index 5f12858..7028532 100644 --- a/src/io/analog/AnalogOutput.cpp +++ b/src/io/analog/AnalogOutput.cpp @@ -33,7 +33,7 @@ static void analog_output_on_write_request(UA_Server *server, const UA_DataValue *data) { AnalogOutput * this_ptr = reinterpret_cast(nodeContext); - bool const voltage = *(UA_Float *)(data->value.data); + float const voltage = *(UA_Float *)(data->value.data); this_ptr->onWriteRequest(server, nodeid, voltage); } From f2c6062da9ce946fa750e5ee86bf9b9cbfe99ef9 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Aug 2024 10:25:55 +0200 Subject: [PATCH 12/29] Fix numbering of analog outputs to be consistent with printed markings on Opta's case. --- examples/opcua_server/opcua_server.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 050dc5f..53a359a 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -300,7 +300,7 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_out_name[32] = {0}; - snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output I%d", a + 1); + snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output O%d", a - OA_CH_6 + 1); exp_analog->analog_output_mgr()->add_analog_output(opc_ua_server, analog_out_name, [i, a](float const voltage) { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); }); } From 6f03ad0a7127cf363a60204231152ac6812e5b8c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 28 Aug 2024 10:34:08 +0200 Subject: [PATCH 13/29] Fix: channel ordering to match markings on case. --- examples/opcua_server/opcua_server.ino | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 53a359a..8f64272 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -269,7 +269,10 @@ void setup() { auto const exp_analog = opta_expansion_manager_opcua->create_analog_expansion(i); - for(int a = OA_CH_0; a <= OA_CH_5; a++) + std::list ANALOG_EXPANSION_MODULE_ANALOG_INPUT_LIST = {OA_CH_0, OA_CH_1, OA_CH_2, OA_CH_3, OA_CH_5, OA_CH_6}; + + int input_num = 1; + for (int const a : ANALOG_EXPANSION_MODULE_ANALOG_INPUT_LIST) { /* Configure analog expansion module analog channels as analog inputs. */ AnalogExpansion::beginChannelAsAdc(OptaController, @@ -283,11 +286,15 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_in_name[32] = {0}; - snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", a + 1); + snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", input_num); exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); }); + input_num++; } - for(int a = OA_CH_6; a <= OA_CH_7; a++) + std::list ANALOG_EXPANSION_MODULE_ANALOG_OUTPUT_LIST = {OA_CH_4, OA_CH_7}; + + int output_num = 1; + for (int const a : ANALOG_EXPANSION_MODULE_ANALOG_OUTPUT_LIST) { /* Configure analog expansion module analog channels as analog outputs. */ AnalogExpansion::beginChannelAsDac(OptaController, @@ -300,8 +307,9 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_out_name[32] = {0}; - snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output O%d", a - OA_CH_6 + 1); + snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output O%d", output_num); exp_analog->analog_output_mgr()->add_analog_output(opc_ua_server, analog_out_name, [i, a](float const voltage) { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); }); + output_num++; } /* Configure controllable LEDs of analog expansion module. */ From f317b8495f6ab42c1f71341d36269234b0b8d3cc Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 09:17:14 +0200 Subject: [PATCH 14/29] First draft on exposing PWM channels for control. --- examples/opcua_server/opcua_server.ino | 15 +++ src/expansion/AnalogExpansion.cpp | 30 ++++- src/expansion/AnalogExpansion.h | 20 ++- src/io/pwm/PwmOutput.cpp | 165 +++++++++++++++++++++++++ src/io/pwm/PwmOutput.h | 77 ++++++++++++ src/io/pwm/PwmOutputManager.cpp | 92 ++++++++++++++ src/io/pwm/PwmOutputManager.h | 65 ++++++++++ 7 files changed, 452 insertions(+), 12 deletions(-) create mode 100644 src/io/pwm/PwmOutput.cpp create mode 100644 src/io/pwm/PwmOutput.h create mode 100644 src/io/pwm/PwmOutputManager.cpp create mode 100644 src/io/pwm/PwmOutputManager.h diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 8f64272..0049283 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -312,6 +312,21 @@ void setup() output_num++; } + /* Configure PWM outputs. */ + int pwm_output_num = 1; + for (int p = OA_PWM_CH_FIRST; p <= OA_PWM_CH_LAST; p++) + { + char pwm_out_name[32] = {0}; + snprintf(pwm_out_name, sizeof(pwm_out_name), "PWM%d", pwm_output_num); + exp_analog->pwm_output_mgr()->add_pwm_output(opc_ua_server, + pwm_out_name, + [i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms) + { + reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms); + }); + pwm_output_num++; + } + /* Configure controllable LEDs of analog expansion module. */ for (int l = 0; l < OA_LED_NUM; l++) { diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index d8122c9..5ce85ea 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -24,37 +24,55 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogInputManager::SharedPtr AnalogExpansion::analog_input_mgr() +AnalogInputManager::SharedPtr +AnalogExpansion::analog_input_mgr() { if (!_analog_input_mgr) { _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::analog_input_mgr: AnalogInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _analog_input_mgr; } -AnalogOutputManager::SharedPtr AnalogExpansion::analog_output_mgr() +AnalogOutputManager::SharedPtr +AnalogExpansion::analog_output_mgr() { if (!_analog_output_mgr) { _analog_output_mgr = opcua::AnalogOutputManager::create(_server, _node_id); if (!_analog_output_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::analog_output_mgr: AnalogOutputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogOutputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _analog_output_mgr; } -LedManager::SharedPtr AnalogExpansion::led_mgr() +PwmOutputManager::SharedPtr +AnalogExpansion::pwm_output_mgr() +{ + if (!_pwm_output_mgr) + { + _pwm_output_mgr = opcua::PwmOutputManager::create(_server, _node_id); + if (!_pwm_output_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: PwmOutputManager::create(...) failed.", __PRETTY_FUNCTION__); + } + + return _pwm_output_mgr; +} + +LedManager::SharedPtr +AnalogExpansion::led_mgr() { if (!_led_mgr) { _led_mgr = opcua::LedManager::create(_server, _node_id); if (!_led_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogExpansion::led_mgr: LedManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); } return _led_mgr; diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 93e8632..72cad4e 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -18,6 +18,7 @@ #include #include "../io/led/LedManager.h" +#include "../io/pwm/PwmOutputManager.h" #include "../io/analog/AnalogInputManager.h" #include "../io/analog/AnalogOutputManager.h" @@ -38,7 +39,11 @@ class AnalogExpansion : public Expansion typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server *server, UA_NodeId const parent_node_id, uint8_t const exp_num) + static SharedPtr + create( + UA_Server *server, + UA_NodeId const parent_node_id, + uint8_t const exp_num) { char display_name[64] = {0}; snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Analog", exp_num); @@ -53,17 +58,19 @@ class AnalogExpansion : public Expansion } - AnalogExpansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name) + AnalogExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) : Expansion(server, parent_node_id, display_name, node_name, model_name) { } AnalogInputManager::SharedPtr analog_input_mgr(); AnalogOutputManager::SharedPtr analog_output_mgr(); + PwmOutputManager::SharedPtr pwm_output_mgr(); LedManager::SharedPtr led_mgr(); @@ -71,6 +78,7 @@ class AnalogExpansion : public Expansion private: AnalogInputManager::SharedPtr _analog_input_mgr; AnalogOutputManager::SharedPtr _analog_output_mgr; + PwmOutputManager::SharedPtr _pwm_output_mgr; LedManager::SharedPtr _led_mgr; }; diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp new file mode 100644 index 0000000..0f86446 --- /dev/null +++ b/src/io/pwm/PwmOutput.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "PwmOutput.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * FUNCTION DEFINITION + **************************************************************************************/ + +static void +pwm_output_on_write_request_pwm_period( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + PwmOutput * this_ptr = reinterpret_cast(nodeContext); + uint32_t const pwm_period_ms = *(UA_UInt32 *)(data->value.data); + this_ptr->onWriteRequestPwmPeriod(server, nodeid, pwm_period_ms); +} + +static void +pwm_output_on_write_request_pwm_pulse_width( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + PwmOutput * this_ptr = reinterpret_cast(nodeContext); + uint32_t const pwm_pulse_width_ms = *(UA_UInt32 *)(data->value.data); + this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_ms); +} + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +PwmOutput::PwmOutput( + UA_NodeId const & node_id, + SetPwmFunc const set_pwm_func) + : _node_id{node_id} + , _set_pwm_func{set_pwm_func} + , _pwm_period_ms{0} + , _pwm_pulse_width_ms{0} +{ + +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +PwmOutput::SharedPtr +PwmOutput::create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + SetPwmFunc const set_pwm_func) +{ + UA_StatusCode rc = UA_STATUSCODE_GOOD; + + UA_VariableAttributes pwm_out_period_value_attr = UA_VariableAttributes_default; + + UA_Boolean pwm_output_period_value = 0; + UA_Variant_setScalar(&pwm_out_period_value_attr.value, &pwm_output_period_value, &UA_TYPES[UA_TYPES_UINT32]); + + pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); + pwm_out_period_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; + pwm_out_period_value_attr.accessLevel = + UA_ACCESSLEVELMASK_READ | + UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_STATUSWRITE | + UA_ACCESSLEVELMASK_TIMESTAMPWRITE; /* Status and timestamp write access necessary for opcua-client. */ + + UA_NodeId node_id; + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "Value"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + pwm_out_period_value_attr, + NULL, + &node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + /* Create an instance of AnalogOutput here. */ + auto const instance_ptr = std::make_shared(node_id, set_pwm_func); + + rc = UA_Server_setNodeContext(server, node_id, reinterpret_cast(instance_ptr.get())); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + UA_ValueCallback callback; + callback.onRead = NULL; + callback.onWrite = pwm_output_on_write_request_pwm_period; + rc = UA_Server_setVariableNode_valueCallback(server, node_id, callback); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + return instance_ptr; +} + +void +PwmOutput::onWriteRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * node_id, + uint32_t const pwm_period_ms) +{ + _pwm_period_ms = pwm_period_ms; + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms); + _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); +} + +void +PwmOutput::onWriteRequestPwmPulseWidth( + UA_Server * server, + UA_NodeId const * node_id, + uint32_t const pwm_pulse_width_ms) +{ + _pwm_pulse_width_ms = pwm_pulse_width_ms; + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_pulse_width_ms); + _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/pwm/PwmOutput.h b/src/io/pwm/PwmOutput.h new file mode 100644 index 0000000..147a63f --- /dev/null +++ b/src/io/pwm/PwmOutput.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "../../open62541.h" + +#include +#include + +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class PwmOutput +{ +public: + typedef std::shared_ptr SharedPtr; + typedef std::function SetPwmFunc; + + + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + SetPwmFunc const set_pwm_func); + + + PwmOutput( + UA_NodeId const & node_id, + SetPwmFunc const set_pwm_func); + + + void + onWriteRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * node_id, + uint32_t const pwm_period_ms); + + void + onWriteRequestPwmPulseWidth( + UA_Server * server, + UA_NodeId const * node_id, + uint32_t const pwm_pulse_width_ms); + + +private: + UA_NodeId _node_id; + SetPwmFunc const _set_pwm_func; + uint32_t _pwm_period_ms, _pwm_pulse_width_ms; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/pwm/PwmOutputManager.cpp b/src/io/pwm/PwmOutputManager.cpp new file mode 100644 index 0000000..87decc0 --- /dev/null +++ b/src/io/pwm/PwmOutputManager.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "PwmOutputManager.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +PwmOutputManager::PwmOutputManager( + UA_NodeId const & node_id) + : _node_id{node_id} +{ + +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +PwmOutputManager::SharedPtr +PwmOutputManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) +{ + UA_StatusCode rc = UA_STATUSCODE_GOOD; + + UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Outputs"); + UA_NodeId node_id; + rc = UA_Server_addObjectNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_QUALIFIEDNAME(1, "PwmOutputs"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), + oAttr, + NULL, + &node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + auto const instance_ptr = std::make_shared(node_id); + return instance_ptr; +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +void +PwmOutputManager::add_pwm_output( + UA_Server * server, + const char * display_name, + PwmOutput::SetPwmFunc const set_pwm_func) +{ + auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func); + if (!pwm_output) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: AnalogOutput::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); + return; + } + _pwm_output_list.push_back(pwm_output); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/pwm/PwmOutputManager.h b/src/io/pwm/PwmOutputManager.h new file mode 100644 index 0000000..217736a --- /dev/null +++ b/src/io/pwm/PwmOutputManager.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "../../open62541.h" + +#include +#include + +#include "PwmOutput.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class PwmOutputManager +{ +public: + typedef std::shared_ptr SharedPtr; + + + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); + + + PwmOutputManager(UA_NodeId const & node_id); + + + void + add_pwm_output( + UA_Server * server, + const char * display_name, + PwmOutput::SetPwmFunc const set_pwm_func); + + +private: + UA_NodeId _node_id; + std::list _pwm_output_list; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ From 7d211016de1b2ecfff42cce05454a1ef4054fba8 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 09:19:24 +0200 Subject: [PATCH 15/29] Move AnalogExpansion::create implementation into .cpp file. --- src/expansion/AnalogExpansion.cpp | 18 ++++++++++++++++++ src/expansion/AnalogExpansion.h | 14 +------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 5ce85ea..1be64f9 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -24,6 +24,24 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ +AnalogExpansion::SharedPtr +AnalogExpansion::create( + UA_Server *server, + UA_NodeId const parent_node_id, + uint8_t const exp_num) +{ + char display_name[64] = {0}; + snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Analog", exp_num); + + char node_name[32] = {0}; + snprintf(node_name, sizeof(node_name), "AnaExp_%d", exp_num); + + char model_name[] = {"AFX00007"}; + + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); + return instance_ptr; +} + AnalogInputManager::SharedPtr AnalogExpansion::analog_input_mgr() { diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 72cad4e..37f1fc8 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -43,19 +43,7 @@ class AnalogExpansion : public Expansion create( UA_Server *server, UA_NodeId const parent_node_id, - uint8_t const exp_num) - { - char display_name[64] = {0}; - snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Analog", exp_num); - - char node_name[32] = {0}; - snprintf(node_name, sizeof(node_name), "AnaExp_%d", exp_num); - - char model_name[] = {"AFX00007"}; - - auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); - return instance_ptr; - } + uint8_t const exp_num); AnalogExpansion( From 14934f6ce2f0b5bcc3761d1f1523bfce35174f93 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 10:09:54 +0200 Subject: [PATCH 16/29] Hide AnalogInput/AnalogOutput/PwmOutput/LedOutput-Manager classes so that the user only directly adds those components. --- examples/opcua_server/opcua_server.ino | 50 +++++++++----- src/expansion/AnalogExpansion.cpp | 92 ++++++++++++++------------ src/expansion/AnalogExpansion.h | 30 +++++++-- src/io/analog/AnalogInput.cpp | 46 +++++++------ src/io/analog/AnalogInput.h | 21 ++++-- src/io/analog/AnalogInputManager.cpp | 22 +++--- src/io/analog/AnalogInputManager.h | 18 +++-- src/io/analog/AnalogOutput.cpp | 49 ++++++++------ src/io/analog/AnalogOutput.h | 22 ++++-- src/io/analog/AnalogOutputManager.cpp | 22 +++--- src/io/analog/AnalogOutputManager.h | 19 ++++-- src/io/led/Led.cpp | 47 +++++++------ src/io/led/Led.h | 22 ++++-- src/io/led/LedManager.cpp | 22 +++--- src/io/led/LedManager.h | 12 +++- 15 files changed, 312 insertions(+), 182 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 0049283..0f287ec 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -287,7 +287,13 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_in_name[32] = {0}; snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", input_num); - exp_analog->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, a]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); }); + exp_analog->add_analog_input( + opc_ua_server, + analog_in_name, + [i, a]() + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); + }); input_num++; } @@ -308,7 +314,13 @@ void setup() /* Expose analog inputs as readable OPC UA properties. */ char analog_out_name[32] = {0}; snprintf(analog_out_name, sizeof(analog_out_name), "Analog Output O%d", output_num); - exp_analog->analog_output_mgr()->add_analog_output(opc_ua_server, analog_out_name, [i, a](float const voltage) { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); }); + exp_analog->add_analog_output( + opc_ua_server, + analog_out_name, + [i, a](float const voltage) + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); + }); output_num++; } @@ -318,12 +330,13 @@ void setup() { char pwm_out_name[32] = {0}; snprintf(pwm_out_name, sizeof(pwm_out_name), "PWM%d", pwm_output_num); - exp_analog->pwm_output_mgr()->add_pwm_output(opc_ua_server, - pwm_out_name, - [i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms) - { - reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms); - }); + exp_analog->add_pwm_output( + opc_ua_server, + pwm_out_name, + [i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms) + { + reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms); + }); pwm_output_num++; } @@ -332,16 +345,17 @@ void setup() { char led_name[32] = {0}; snprintf(led_name, sizeof(led_name), "LED%d", l + 1); - exp_analog->led_mgr()->add_led_output(opc_ua_server, - led_name, - [i, l](bool const value) - { - AnalogExpansion * ana_exp_ptr = reinterpret_cast(OptaController.getExpansionPtr(i)); - if (value) - ana_exp_ptr->switchLedOn(l); - else - ana_exp_ptr->switchLedOff(l); - }); + exp_analog->add_led_output( + opc_ua_server, + led_name, + [i, l](bool const value) + { + AnalogExpansion * ana_exp_ptr = reinterpret_cast(OptaController.getExpansionPtr(i)); + if (value) + ana_exp_ptr->switchLedOn(l); + else + ana_exp_ptr->switchLedOff(l); + }); } } } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 1be64f9..47e42af 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -20,6 +20,32 @@ namespace opcua { +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +AnalogExpansion::AnalogExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) + : Expansion(server, parent_node_id, display_name, node_name, model_name) + , _analog_input_mgr{opcua::AnalogInputManager::create(_server, _node_id)} + , _analog_output_mgr{opcua::AnalogOutputManager::create(_server, _node_id)} + , _pwm_output_mgr{opcua::PwmOutputManager::create(_server, _node_id)} + , _led_mgr{opcua::LedManager::create(_server, _node_id)} +{ + if (!_analog_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_analog_output_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogOutputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_pwm_output_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: PwmOutputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_led_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); +} + /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ @@ -42,58 +68,40 @@ AnalogExpansion::create( return instance_ptr; } -AnalogInputManager::SharedPtr -AnalogExpansion::analog_input_mgr() +void +AnalogExpansion::add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func) { - if (!_analog_input_mgr) - { - _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); - if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _analog_input_mgr; + _analog_input_mgr->add_analog_input(server, display_name, on_read_request_func); } -AnalogOutputManager::SharedPtr -AnalogExpansion::analog_output_mgr() +void +AnalogExpansion::add_analog_output( + UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func) { - if (!_analog_output_mgr) - { - _analog_output_mgr = opcua::AnalogOutputManager::create(_server, _node_id); - if (!_analog_output_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogOutputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _analog_output_mgr; + _analog_output_mgr->add_analog_output(server, display_name, on_write_request_func); } -PwmOutputManager::SharedPtr -AnalogExpansion::pwm_output_mgr() +void +AnalogExpansion::add_pwm_output( + UA_Server * server, + const char * display_name, + PwmOutput::SetPwmFunc const set_pwm_func) { - if (!_pwm_output_mgr) - { - _pwm_output_mgr = opcua::PwmOutputManager::create(_server, _node_id); - if (!_pwm_output_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: PwmOutputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _pwm_output_mgr; + _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func); } -LedManager::SharedPtr -AnalogExpansion::led_mgr() +void +AnalogExpansion::add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state) { - if (!_led_mgr) - { - _led_mgr = opcua::LedManager::create(_server, _node_id); - if (!_led_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _led_mgr; + _led_mgr->add_led_output(server, display_name, on_set_led_state); } /************************************************************************************** diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 37f1fc8..d839af1 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -51,16 +51,32 @@ class AnalogExpansion : public Expansion UA_NodeId const parent_node_id, char * display_name, char * node_name, - char * model_name) - : Expansion(server, parent_node_id, display_name, node_name, model_name) - { } + char * model_name); - AnalogInputManager::SharedPtr analog_input_mgr(); - AnalogOutputManager::SharedPtr analog_output_mgr(); - PwmOutputManager::SharedPtr pwm_output_mgr(); - LedManager::SharedPtr led_mgr(); + void + add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func); + + void + add_analog_output( + UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func); + void + add_pwm_output( + UA_Server * server, + const char * display_name, + PwmOutput::SetPwmFunc const set_pwm_func); + + void + add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state); private: diff --git a/src/io/analog/AnalogInput.cpp b/src/io/analog/AnalogInput.cpp index 17248cc..0d49ea8 100644 --- a/src/io/analog/AnalogInput.cpp +++ b/src/io/analog/AnalogInput.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void analog_input_on_read_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +analog_input_on_read_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { AnalogInput * this_ptr = reinterpret_cast(nodeContext); this_ptr->onReadRequest(server, nodeid); @@ -40,7 +42,9 @@ static void analog_input_on_read_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -AnalogInput::AnalogInput(UA_NodeId const & node_id, OnReadRequestFunc const on_read_request) +AnalogInput::AnalogInput( + UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request) : _node_id{node_id} , _on_read_request{on_read_request} { @@ -51,10 +55,12 @@ AnalogInput::AnalogInput(UA_NodeId const & node_id, OnReadRequestFunc const on_r * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogInput::SharedPtr AnalogInput::create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnReadRequestFunc const on_read_request) +AnalogInput::SharedPtr +AnalogInput::create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnReadRequestFunc const on_read_request) { UA_VariableAttributes analog_input_value_attr = UA_VariableAttributes_default; @@ -81,8 +87,7 @@ AnalogInput::SharedPtr AnalogInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogInput::create: UA_Server_addVariableNode(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -93,8 +98,7 @@ AnalogInput::SharedPtr AnalogInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogInput::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -105,15 +109,17 @@ AnalogInput::SharedPtr AnalogInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogInput::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void AnalogInput::onReadRequest(UA_Server * server, UA_NodeId const * node_id) +void +AnalogInput::onReadRequest( + UA_Server * server, + UA_NodeId const * node_id) { /* Obtain the value of the analog input pin. */ float const in_x_val = _on_read_request(); @@ -124,7 +130,7 @@ void AnalogInput::onReadRequest(UA_Server * server, UA_NodeId const * node_id) UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_FLOAT]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogInput::onReadRequest: value = %f", in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %f", __PRETTY_FUNCTION__, in_x_val); } /************************************************************************************** diff --git a/src/io/analog/AnalogInput.h b/src/io/analog/AnalogInput.h index 2585702..8113b19 100644 --- a/src/io/analog/AnalogInput.h +++ b/src/io/analog/AnalogInput.h @@ -37,14 +37,23 @@ class AnalogInput typedef std::shared_ptr SharedPtr; typedef std::function OnReadRequestFunc; - static SharedPtr create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnReadRequestFunc const on_read_request); - AnalogInput(UA_NodeId const & node_id, OnReadRequestFunc const on_read_request); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnReadRequestFunc const on_read_request); - void onReadRequest(UA_Server * server, UA_NodeId const * node_id); + + AnalogInput( + UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request); + + + void onReadRequest( + UA_Server * server, + UA_NodeId const * node_id); private: diff --git a/src/io/analog/AnalogInputManager.cpp b/src/io/analog/AnalogInputManager.cpp index 6fe3bdd..f8fb38f 100644 --- a/src/io/analog/AnalogInputManager.cpp +++ b/src/io/analog/AnalogInputManager.cpp @@ -24,17 +24,21 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -AnalogInputManager::AnalogInputManager(UA_NodeId const & node_id) +AnalogInputManager::AnalogInputManager( + UA_NodeId const & node_id) : _node_id{node_id} { - /* Nothing happens here. */ + } /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogInputManager::SharedPtr AnalogInputManager::create(UA_Server * server, UA_NodeId const parent_node_id) +AnalogInputManager::SharedPtr +AnalogInputManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -53,7 +57,7 @@ AnalogInputManager::SharedPtr AnalogInputManager::create(UA_Server * server, UA_ if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogInputManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -65,13 +69,15 @@ AnalogInputManager::SharedPtr AnalogInputManager::create(UA_Server * server, UA_ * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void AnalogInputManager::add_analog_input(UA_Server * server, - const char * display_name, - AnalogInput::OnReadRequestFunc const on_read_request_func) +void +AnalogInputManager::add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func) { auto const analog_input = AnalogInput::create(server, _node_id, display_name, on_read_request_func); if (!analog_input) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogInputManager::add_digital_input: AnalogInput::create(...) failed: returned nullptr"); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInput::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; } _analog_input_list.push_back(analog_input); diff --git a/src/io/analog/AnalogInputManager.h b/src/io/analog/AnalogInputManager.h index e063dc3..78ad2e1 100644 --- a/src/io/analog/AnalogInputManager.h +++ b/src/io/analog/AnalogInputManager.h @@ -36,13 +36,21 @@ class AnalogInputManager public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); - AnalogInputManager(UA_NodeId const & node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); - void add_analog_input(UA_Server * server, - const char * display_name, - AnalogInput::OnReadRequestFunc const on_read_request_func); + + AnalogInputManager( + UA_NodeId const & node_id); + + void + add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func); private: diff --git a/src/io/analog/AnalogOutput.cpp b/src/io/analog/AnalogOutput.cpp index 7028532..5b76ffe 100644 --- a/src/io/analog/AnalogOutput.cpp +++ b/src/io/analog/AnalogOutput.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void analog_output_on_write_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +analog_output_on_write_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { AnalogOutput * this_ptr = reinterpret_cast(nodeContext); float const voltage = *(UA_Float *)(data->value.data); @@ -41,7 +43,9 @@ static void analog_output_on_write_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -AnalogOutput::AnalogOutput(UA_NodeId const & node_id, OnWriteRequestFunc const on_write_request) +AnalogOutput::AnalogOutput( + UA_NodeId const & node_id, + OnWriteRequestFunc const on_write_request) : _node_id{node_id} , _on_write_request{on_write_request} { @@ -52,16 +56,18 @@ AnalogOutput::AnalogOutput(UA_NodeId const & node_id, OnWriteRequestFunc const o * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogOutput::SharedPtr AnalogOutput::create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnWriteRequestFunc const on_write_request) +AnalogOutput::SharedPtr +AnalogOutput::create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnWriteRequestFunc const on_write_request) { UA_StatusCode rc = UA_STATUSCODE_GOOD; UA_VariableAttributes analog_output_value_attr = UA_VariableAttributes_default; - UA_Boolean analog_output_value = 0.; + UA_Float analog_output_value = 0.; UA_Variant_setScalar(&analog_output_value_attr.value, &analog_output_value, &UA_TYPES[UA_TYPES_FLOAT]); analog_output_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); @@ -84,7 +90,7 @@ AnalogOutput::SharedPtr AnalogOutput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogOutput::create: UA_Server_addVariableNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -95,8 +101,7 @@ AnalogOutput::SharedPtr AnalogOutput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogOutput::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -107,18 +112,20 @@ AnalogOutput::SharedPtr AnalogOutput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogOutput::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void AnalogOutput::onWriteRequest(UA_Server * server, UA_NodeId const * node_id, float const voltage) +void +AnalogOutput::onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + float const voltage) { - /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogOutput::onWriteRequest: voltage = %0.2f", voltage); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: voltage = %0.2f", __PRETTY_FUNCTION__, voltage); _on_write_request(voltage); } diff --git a/src/io/analog/AnalogOutput.h b/src/io/analog/AnalogOutput.h index 6402e1d..ed98df7 100644 --- a/src/io/analog/AnalogOutput.h +++ b/src/io/analog/AnalogOutput.h @@ -37,14 +37,24 @@ class AnalogOutput typedef std::shared_ptr SharedPtr; typedef std::function OnWriteRequestFunc; - static SharedPtr create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnWriteRequestFunc const on_write_request); - AnalogOutput(UA_NodeId const & node_id, OnWriteRequestFunc const on_write_request); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnWriteRequestFunc const on_write_request); - void onWriteRequest(UA_Server * server, UA_NodeId const * node_id, float const voltage); + + AnalogOutput( + UA_NodeId const & node_id, + OnWriteRequestFunc const on_write_request); + + + void onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + float const voltage); private: diff --git a/src/io/analog/AnalogOutputManager.cpp b/src/io/analog/AnalogOutputManager.cpp index 628c455..39d795c 100644 --- a/src/io/analog/AnalogOutputManager.cpp +++ b/src/io/analog/AnalogOutputManager.cpp @@ -24,17 +24,21 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -AnalogOutputManager::AnalogOutputManager(UA_NodeId const & node_id) +AnalogOutputManager::AnalogOutputManager( + UA_NodeId const & node_id) : _node_id{node_id} { - /* Nothing happens here. */ + } /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogOutputManager::SharedPtr AnalogOutputManager::create(UA_Server * server, UA_NodeId const parent_node_id) +AnalogOutputManager::SharedPtr +AnalogOutputManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -53,7 +57,7 @@ AnalogOutputManager::SharedPtr AnalogOutputManager::create(UA_Server * server, U if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "AnalogOutputManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -65,13 +69,15 @@ AnalogOutputManager::SharedPtr AnalogOutputManager::create(UA_Server * server, U * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void AnalogOutputManager::add_analog_output(UA_Server * server, - const char * display_name, - AnalogOutput::OnWriteRequestFunc const on_write_request_func) +void +AnalogOutputManager::add_analog_output( + UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func) { auto const analog_output = AnalogOutput::create(server, _node_id, display_name, on_write_request_func); if (!analog_output) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AnalogOutputManager::add_analog_output: AnalogOutput::create(...) failed: returned nullptr"); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogOutput::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; } _analog_output_list.push_back(analog_output); diff --git a/src/io/analog/AnalogOutputManager.h b/src/io/analog/AnalogOutputManager.h index 5268a0c..c80ffb2 100644 --- a/src/io/analog/AnalogOutputManager.h +++ b/src/io/analog/AnalogOutputManager.h @@ -36,13 +36,22 @@ class AnalogOutputManager public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); - AnalogOutputManager(UA_NodeId const & node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); - void add_analog_output(UA_Server * server, - const char * display_name, - AnalogOutput::OnWriteRequestFunc const on_write_request_func); + + AnalogOutputManager( + UA_NodeId const & node_id); + + + void + add_analog_output( + UA_Server * server, + const char * display_name, + AnalogOutput::OnWriteRequestFunc const on_write_request_func); private: diff --git a/src/io/led/Led.cpp b/src/io/led/Led.cpp index a48be11..7b93878 100644 --- a/src/io/led/Led.cpp +++ b/src/io/led/Led.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void led_on_write_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +led_on_write_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { bool const value = *(UA_Boolean *)(data->value.data) == true; Led * this_ptr = reinterpret_cast(nodeContext); @@ -41,7 +43,9 @@ static void led_on_write_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -Led::Led(UA_NodeId const & node_id, OnSetLedStateFunc const on_set_led_state) +Led::Led( + UA_NodeId const & node_id, + OnSetLedStateFunc const on_set_led_state) : _node_id{node_id} , _on_set_led_state{on_set_led_state} { @@ -52,10 +56,12 @@ Led::Led(UA_NodeId const & node_id, OnSetLedStateFunc const on_set_led_state) * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -Led::SharedPtr Led::create(UA_Server *server, - UA_NodeId const &parent_node_id, - const char *display_name, - OnSetLedStateFunc const on_set_led_state) +Led::SharedPtr +Led::create( + UA_Server *server, + UA_NodeId const &parent_node_id, + const char *display_name, + OnSetLedStateFunc const on_set_led_state) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -84,7 +90,7 @@ Led::SharedPtr Led::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Led::create: UA_Server_addVariableNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -95,8 +101,7 @@ Led::SharedPtr Led::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Led::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -107,18 +112,20 @@ Led::SharedPtr Led::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Led::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void Led::onWriteRequest(UA_Server * server, UA_NodeId const * node_id, bool const value) +void +Led::onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + bool const value) { - /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Led::onWriteRequest: value = %d", value); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, value); _on_set_led_state(value); } diff --git a/src/io/led/Led.h b/src/io/led/Led.h index 86c87d8..6c9b62a 100644 --- a/src/io/led/Led.h +++ b/src/io/led/Led.h @@ -35,14 +35,24 @@ class Led typedef std::shared_ptr SharedPtr; typedef std::function OnSetLedStateFunc; - static SharedPtr create(UA_Server *server, - UA_NodeId const &parent_node_id, - const char *display_name, - OnSetLedStateFunc const on_set_led_state); - Led(UA_NodeId const &node_id, OnSetLedStateFunc const on_set_led_state); + static SharedPtr + create( + UA_Server *server, + UA_NodeId const &parent_node_id, + const char *display_name, + OnSetLedStateFunc const on_set_led_state); - void onWriteRequest(UA_Server * server, UA_NodeId const * node_id, bool const value); + + Led( + UA_NodeId const &node_id, + OnSetLedStateFunc const on_set_led_state); + + + void onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + bool const value); private: diff --git a/src/io/led/LedManager.cpp b/src/io/led/LedManager.cpp index e9a5009..715c901 100644 --- a/src/io/led/LedManager.cpp +++ b/src/io/led/LedManager.cpp @@ -24,17 +24,21 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -LedManager::LedManager(UA_NodeId const & node_id) +LedManager::LedManager( + UA_NodeId const & node_id) : _node_id{node_id} { - /* Nothing happens here. */ + } /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -LedManager::SharedPtr LedManager::create(UA_Server * server, UA_NodeId const parent_node_id) +LedManager::SharedPtr +LedManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -53,7 +57,7 @@ LedManager::SharedPtr LedManager::create(UA_Server * server, UA_NodeId const par if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "LedManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -65,13 +69,15 @@ LedManager::SharedPtr LedManager::create(UA_Server * server, UA_NodeId const par * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void LedManager::add_led_output(UA_Server * server, - const char * display_name, - Led::OnSetLedStateFunc const on_set_led_state) +void +LedManager::add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state) { auto const led = Led::create(server, _node_id, display_name, on_set_led_state); if (!led) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "LedManager::add_led_output: Led::create(...) failed: returned nullptr"); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: Led::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; } _led_list.push_back(led); diff --git a/src/io/led/LedManager.h b/src/io/led/LedManager.h index 3be94c3..f5b0260 100644 --- a/src/io/led/LedManager.h +++ b/src/io/led/LedManager.h @@ -36,11 +36,19 @@ class LedManager public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); + LedManager(UA_NodeId const & node_id); - void add_led_output(UA_Server * server, const char * display_name, Led::OnSetLedStateFunc const on_set_led_state); + + void add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state); private: From 994fd4dd6a9577423bd33e71115321232ca8181a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 10:12:11 +0200 Subject: [PATCH 17/29] Add note concering content of extras/precompile (only relevant for maintainers). --- extras/precompile/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extras/precompile/README.md b/extras/precompile/README.md index 5aa5dc8..a6b1aa0 100644 --- a/extras/precompile/README.md +++ b/extras/precompile/README.md @@ -1,6 +1,9 @@ :floppy_disk: Precompile `open62541` library for `cortex-m7` ============================================================ The following instructions can be used to pre-compile the `open62541` library for `cortex-m7`. + +**Note**: these steps are only relevant for the maintainers of this library. + ```bash ./docker-build.sh ./docker-run.sh From 28b71e4c218133196176c41a06446b1681d699da Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 10:46:27 +0200 Subject: [PATCH 18/29] Unify format of function definition across all files. --- src/Opta.cpp | 43 ++++++++++++---------- src/Opta.h | 9 +++-- src/OptaExpansionManager.cpp | 12 +++++-- src/OptaExpansionManager.h | 7 ++-- src/OptaVariant.cpp | 16 ++++++--- src/OptaVariant.h | 14 ++++++-- src/expansion/DigitalExpansion.cpp | 15 ++++---- src/expansion/DigitalExpansion.h | 11 +++--- src/expansion/DigitalMechExpansion.h | 17 +++++---- src/expansion/DigitalStSolidExpansion.h | 17 +++++---- src/expansion/Expansion.cpp | 22 ++++++------ src/expansion/Expansion.h | 11 +++--- src/io/button/UserButton.cpp | 42 ++++++++++++---------- src/io/button/UserButton.h | 16 +++++++-- src/io/digital/DigitalInput.cpp | 46 +++++++++++++----------- src/io/digital/DigitalInput.h | 22 ++++++++---- src/io/digital/DigitalInputManager.cpp | 20 +++++++---- src/io/digital/DigitalInputManager.h | 19 +++++++--- src/io/relay/Relay.cpp | 47 ++++++++++++++----------- src/io/relay/Relay.h | 23 ++++++++---- src/io/relay/RelayManager.cpp | 20 +++++++---- src/io/relay/RelayManager.h | 17 +++++++-- 22 files changed, 297 insertions(+), 169 deletions(-) diff --git a/src/Opta.cpp b/src/Opta.cpp index be58299..a05efcf 100644 --- a/src/Opta.cpp +++ b/src/Opta.cpp @@ -24,7 +24,9 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -Opta::Opta(UA_Server * server, UA_NodeId const & node_id) +Opta::Opta( + UA_Server * server, + UA_NodeId const & node_id) : _server{server} , _node_id{node_id} , _analog_input_mgr{nullptr} @@ -34,14 +36,17 @@ Opta::Opta(UA_Server * server, UA_NodeId const & node_id) { _usr_button = opcua::UserButton::create(_server, _node_id); if (!_usr_button) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::Ctor: UserButton::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: UserButton::create(...) failed.", __PRETTY_FUNCTION__); } /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_type) +Opta::SharedPtr +Opta::create( + UA_Server * server, + OptaVariant::Type const opta_type) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -60,8 +65,7 @@ Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_ty if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Opta::create: UA_Server_addObjectNode(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -81,8 +85,7 @@ Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_ty if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Opta::create: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -102,8 +105,7 @@ Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_ty if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Opta::create: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -123,8 +125,7 @@ Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_ty if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Opta::create: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -132,49 +133,53 @@ Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_ty return instance_ptr; } -AnalogInputManager::SharedPtr Opta::analog_input_mgr() +AnalogInputManager::SharedPtr +Opta::analog_input_mgr() { if (!_analog_input_mgr) { _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::analog_input_mgr: AnalogInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _analog_input_mgr; } -DigitalInputManager::SharedPtr Opta::digital_input_mgr() +DigitalInputManager::SharedPtr +Opta::digital_input_mgr() { if (!_digital_input_mgr) { _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); if (!_digital_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::digital_input_mgr: DigitalInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _digital_input_mgr; } -RelayManager::SharedPtr Opta::relay_mgr() +RelayManager::SharedPtr +Opta::relay_mgr() { if (!_relay_mgr) { _relay_mgr = opcua::RelayManager::create(_server, _node_id); if (!_relay_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::relay_mgr: RelayManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); } return _relay_mgr; } -LedManager::SharedPtr Opta::led_mgr() +LedManager::SharedPtr +Opta::led_mgr() { if (!_led_mgr) { _led_mgr = opcua::LedManager::create(_server, _node_id); if (!_led_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::led_mgr: LedManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); } return _led_mgr; diff --git a/src/Opta.h b/src/Opta.h index d3be5cf..5f9962d 100644 --- a/src/Opta.h +++ b/src/Opta.h @@ -42,10 +42,15 @@ class Opta typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, OptaVariant::Type const opta_type); + static SharedPtr + create( + UA_Server * server, + OptaVariant::Type const opta_type); - Opta(UA_Server * server, UA_NodeId const & node_id); + Opta( + UA_Server * server, + UA_NodeId const & node_id); AnalogInputManager::SharedPtr analog_input_mgr(); diff --git a/src/OptaExpansionManager.cpp b/src/OptaExpansionManager.cpp index 95d55cb..e78911b 100644 --- a/src/OptaExpansionManager.cpp +++ b/src/OptaExpansionManager.cpp @@ -24,7 +24,9 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -DigitalMechExpansion::SharedPtr OptaExpansionManager::create_digital_mechanical_expansion(uint8_t const exp_num) +DigitalMechExpansion::SharedPtr +OptaExpansionManager::create_digital_mechanical_expansion( + uint8_t const exp_num) { auto const exp_mech_opcua = opcua::DigitalMechExpansion::create( _server, @@ -35,7 +37,9 @@ DigitalMechExpansion::SharedPtr OptaExpansionManager::create_digital_mechanical_ return exp_mech_opcua; } -DigitalStSolidExpansion::SharedPtr OptaExpansionManager::create_digital_solid_state_expansion(uint8_t const exp_num) +DigitalStSolidExpansion::SharedPtr +OptaExpansionManager::create_digital_solid_state_expansion( + uint8_t const exp_num) { auto const exp_solid_state_opcua = opcua::DigitalStSolidExpansion::create( _server, @@ -46,7 +50,9 @@ DigitalStSolidExpansion::SharedPtr OptaExpansionManager::create_digital_solid_st return exp_solid_state_opcua; } -AnalogExpansion::SharedPtr OptaExpansionManager::create_analog_expansion(uint8_t const exp_num) +AnalogExpansion::SharedPtr +OptaExpansionManager::create_analog_expansion( + uint8_t const exp_num) { auto const exp_analog_opcua = opcua::AnalogExpansion::create( _server, diff --git a/src/OptaExpansionManager.h b/src/OptaExpansionManager.h index c3fef8d..b9f3fd0 100644 --- a/src/OptaExpansionManager.h +++ b/src/OptaExpansionManager.h @@ -38,12 +38,15 @@ class OptaExpansionManager typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server) { + static SharedPtr + create( + UA_Server * server) { return std::make_shared(server); } - OptaExpansionManager(UA_Server * server) + OptaExpansionManager( + UA_Server * server) : _server{server} { } diff --git a/src/OptaVariant.cpp b/src/OptaVariant.cpp index 4c8e751..8c1b521 100644 --- a/src/OptaVariant.cpp +++ b/src/OptaVariant.cpp @@ -32,7 +32,9 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -bool OptaVariant::get_opta_variant(Type & type) +bool +OptaVariant::get_opta_variant( + Type & type) { OptaBoardInfo * info = boardInfo(); @@ -51,7 +53,9 @@ bool OptaVariant::get_opta_variant(Type & type) return true; } -std::string OptaVariant::toString(Type const type) +std::string +OptaVariant::toString( + Type const type) { switch(type) { @@ -62,13 +66,15 @@ std::string OptaVariant::toString(Type const type) } } -std::string OptaVariant::toSKUString(Type const type) +std::string +OptaVariant::toSKUString( + Type const type) { switch(type) { - case OptaVariant::Type::WiFi: return std::string("AFX00002"); break; + case OptaVariant::Type::WiFi: return std::string("AFX00002"); break; case OptaVariant::Type::RS485: return std::string("AFX00001"); break; - case OptaVariant::Type::Lite: return std::string("AFX00003"); break; + case OptaVariant::Type::Lite: return std::string("AFX00003"); break; default: __builtin_unreachable(); break; } } diff --git a/src/OptaVariant.h b/src/OptaVariant.h index 719da3c..b70a2a4 100644 --- a/src/OptaVariant.h +++ b/src/OptaVariant.h @@ -32,12 +32,20 @@ class OptaVariant OptaVariant() = delete; OptaVariant(OptaVariant const &) = delete; + enum class Type { Lite, RS485, WiFi }; - static bool get_opta_variant(Type & type); - static std::string toString(Type const type); - static std::string toSKUString(Type const type); + static bool + get_opta_variant( + Type & type); + + static std::string + toString( + Type const type); + static std::string + toSKUString( + Type const type); }; /************************************************************************************** diff --git a/src/expansion/DigitalExpansion.cpp b/src/expansion/DigitalExpansion.cpp index 2b72d72..32d01e8 100644 --- a/src/expansion/DigitalExpansion.cpp +++ b/src/expansion/DigitalExpansion.cpp @@ -26,37 +26,40 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -AnalogInputManager::SharedPtr DigitalExpansion::analog_input_mgr() +AnalogInputManager::SharedPtr +DigitalExpansion::analog_input_mgr() { if (!_analog_input_mgr) { _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::analog_input_mgr: AnalogInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _analog_input_mgr; } -DigitalInputManager::SharedPtr DigitalExpansion::digital_input_mgr() +DigitalInputManager::SharedPtr +DigitalExpansion::digital_input_mgr() { if (!_digital_input_mgr) { _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); if (!_digital_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::digital_input_mgr: DigitalInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); } return _digital_input_mgr; } -RelayManager::SharedPtr DigitalExpansion::relay_mgr() +RelayManager::SharedPtr +DigitalExpansion::relay_mgr() { if (!_relay_mgr) { _relay_mgr = opcua::RelayManager::create(_server, _node_id); if (!_relay_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::relay_mgr: RelayManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); } return _relay_mgr; diff --git a/src/expansion/DigitalExpansion.h b/src/expansion/DigitalExpansion.h index c44f173..61ffbe2 100644 --- a/src/expansion/DigitalExpansion.h +++ b/src/expansion/DigitalExpansion.h @@ -38,11 +38,12 @@ class DigitalExpansion : public Expansion typedef std::shared_ptr SharedPtr; - DigitalExpansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name) + DigitalExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) : Expansion(server, parent_node_id, display_name, node_name, model_name) { } diff --git a/src/expansion/DigitalMechExpansion.h b/src/expansion/DigitalMechExpansion.h index 8908487..dd3377d 100644 --- a/src/expansion/DigitalMechExpansion.h +++ b/src/expansion/DigitalMechExpansion.h @@ -32,7 +32,11 @@ class DigitalMechExpansion : public DigitalExpansion typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server *server, UA_NodeId const parent_node_id, uint8_t const exp_num) + static SharedPtr + create( + UA_Server *server, + UA_NodeId const parent_node_id, + uint8_t const exp_num) { char display_name[64] = {0}; snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Digital (Mechanical)", exp_num); @@ -47,11 +51,12 @@ class DigitalMechExpansion : public DigitalExpansion } - DigitalMechExpansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name) + DigitalMechExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) : DigitalExpansion{server, parent_node_id, display_name, node_name, model_name} {} }; diff --git a/src/expansion/DigitalStSolidExpansion.h b/src/expansion/DigitalStSolidExpansion.h index a458fef..e386a12 100644 --- a/src/expansion/DigitalStSolidExpansion.h +++ b/src/expansion/DigitalStSolidExpansion.h @@ -32,7 +32,11 @@ class DigitalStSolidExpansion : public DigitalExpansion typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server *server, UA_NodeId const parent_node_id, uint8_t const exp_num) + static SharedPtr + create( + UA_Server *server, + UA_NodeId const parent_node_id, + uint8_t const exp_num) { char display_name[64] = {0}; snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Digital (Solid State)", exp_num); @@ -47,11 +51,12 @@ class DigitalStSolidExpansion : public DigitalExpansion } - DigitalStSolidExpansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name) + DigitalStSolidExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) : DigitalExpansion{server, parent_node_id, display_name, node_name, model_name} {} }; diff --git a/src/expansion/Expansion.cpp b/src/expansion/Expansion.cpp index 0e4bd36..cd53c6f 100644 --- a/src/expansion/Expansion.cpp +++ b/src/expansion/Expansion.cpp @@ -24,11 +24,12 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -Expansion::Expansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name) +Expansion::Expansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) : _server{server} { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -48,7 +49,7 @@ Expansion::Expansion(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Expansion::Ctor: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return; } @@ -68,8 +69,7 @@ Expansion::Expansion(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Expansion::Ctor: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return; } @@ -89,8 +89,7 @@ Expansion::Expansion(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Expansion::Ctor: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return; } @@ -110,8 +109,7 @@ Expansion::Expansion(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Expansion::Ctor: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return; } } diff --git a/src/expansion/Expansion.h b/src/expansion/Expansion.h index 9ead3ca..fdd3cac 100644 --- a/src/expansion/Expansion.h +++ b/src/expansion/Expansion.h @@ -34,11 +34,12 @@ class Expansion typedef std::shared_ptr SharedPtr; - Expansion(UA_Server * server, - UA_NodeId const parent_node_id, - char * display_name, - char * node_name, - char * model_name); + Expansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name); protected: diff --git a/src/io/button/UserButton.cpp b/src/io/button/UserButton.cpp index 260f09a..2af2059 100644 --- a/src/io/button/UserButton.cpp +++ b/src/io/button/UserButton.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void user_button_on_read_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +user_button_on_read_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { UserButton * this_ptr = reinterpret_cast(nodeContext); this_ptr->onReadRequest(server, nodeid); @@ -40,7 +42,8 @@ static void user_button_on_read_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -UserButton::UserButton(UA_NodeId const & node_id) +UserButton::UserButton( + UA_NodeId const & node_id) : _node_id{node_id} { @@ -50,7 +53,10 @@ UserButton::UserButton(UA_NodeId const & node_id) * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -UserButton::SharedPtr UserButton::create(UA_Server * server, UA_NodeId const & parent_node_id) +UserButton::SharedPtr +UserButton::create( + UA_Server * server, + UA_NodeId const & parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -69,7 +75,7 @@ UserButton::SharedPtr UserButton::create(UA_Server * server, UA_NodeId const & p if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "UserButton::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -100,8 +106,7 @@ UserButton::SharedPtr UserButton::create(UA_Server * server, UA_NodeId const & p if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "UserButton::create: UA_Server_addVariableNode(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -112,8 +117,7 @@ UserButton::SharedPtr UserButton::create(UA_Server * server, UA_NodeId const & p if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "UserButton::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -124,15 +128,17 @@ UserButton::SharedPtr UserButton::create(UA_Server * server, UA_NodeId const & p if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "UserButton::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void UserButton::onReadRequest(UA_Server * server, UA_NodeId const * node_id) +void +UserButton::onReadRequest( + UA_Server * server, + UA_NodeId const * node_id) { /* Obtain the value of the digital input pin. */ pinMode(BTN_USER, INPUT); @@ -144,7 +150,7 @@ void UserButton::onReadRequest(UA_Server * server, UA_NodeId const * node_id) UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_BOOLEAN]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "UserButton::onReadRequest: value = %d", in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, in_x_val); } /************************************************************************************** diff --git a/src/io/button/UserButton.h b/src/io/button/UserButton.h index c0173b4..a462484 100644 --- a/src/io/button/UserButton.h +++ b/src/io/button/UserButton.h @@ -35,11 +35,21 @@ class UserButton public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const & parent_node_id); - UserButton(UA_NodeId const & node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id); - void onReadRequest(UA_Server * server, UA_NodeId const * node_id); + + UserButton( + UA_NodeId const & node_id); + + + void + onReadRequest( + UA_Server * server, + UA_NodeId const * node_id); private: diff --git a/src/io/digital/DigitalInput.cpp b/src/io/digital/DigitalInput.cpp index 864fbd0..a436ed4 100644 --- a/src/io/digital/DigitalInput.cpp +++ b/src/io/digital/DigitalInput.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void digital_input_on_read_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +digital_input_on_read_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { DigitalInput * this_ptr = reinterpret_cast(nodeContext); this_ptr->onReadRequest(server, nodeid); @@ -40,7 +42,9 @@ static void digital_input_on_read_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -DigitalInput::DigitalInput(UA_NodeId const & node_id, OnReadRequestFunc const on_read_request) +DigitalInput::DigitalInput( + UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request) : _node_id{node_id} , _on_read_request{on_read_request} { @@ -51,10 +55,12 @@ DigitalInput::DigitalInput(UA_NodeId const & node_id, OnReadRequestFunc const on * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -DigitalInput::SharedPtr DigitalInput::create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnReadRequestFunc const on_read_request) +DigitalInput::SharedPtr +DigitalInput::create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnReadRequestFunc const on_read_request) { UA_VariableAttributes digital_input_value_attr = UA_VariableAttributes_default; @@ -82,8 +88,7 @@ DigitalInput::SharedPtr DigitalInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "DigitalInput::create: UA_Server_addVariableNode(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -94,8 +99,7 @@ DigitalInput::SharedPtr DigitalInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "DigitalInput::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -106,15 +110,17 @@ DigitalInput::SharedPtr DigitalInput::create(UA_Server * server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "DigitalInput::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void DigitalInput::onReadRequest(UA_Server * server, UA_NodeId const * node_id) +void +DigitalInput::onReadRequest( + UA_Server * server, + UA_NodeId const * node_id) { /* Obtain the value of the digital input pin. */ PinStatus const in_x_val = _on_read_request(); @@ -125,7 +131,7 @@ void DigitalInput::onReadRequest(UA_Server * server, UA_NodeId const * node_id) UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_BOOLEAN]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalInput::onReadRequest: value = %d", in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, in_x_val); } /************************************************************************************** diff --git a/src/io/digital/DigitalInput.h b/src/io/digital/DigitalInput.h index 2b52d14..269b321 100644 --- a/src/io/digital/DigitalInput.h +++ b/src/io/digital/DigitalInput.h @@ -37,14 +37,24 @@ class DigitalInput typedef std::shared_ptr SharedPtr; typedef std::function OnReadRequestFunc; - static SharedPtr create(UA_Server * server, - UA_NodeId const & parent_node_id, - const char * display_name, - OnReadRequestFunc const on_read_request); - DigitalInput(UA_NodeId const & node_id, OnReadRequestFunc const on_read_request); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + OnReadRequestFunc const on_read_request); - void onReadRequest(UA_Server * server, UA_NodeId const * node_id); + + DigitalInput( + UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request); + + + void + onReadRequest( + UA_Server * server, + UA_NodeId const * node_id); private: diff --git a/src/io/digital/DigitalInputManager.cpp b/src/io/digital/DigitalInputManager.cpp index a408adb..3db18d1 100644 --- a/src/io/digital/DigitalInputManager.cpp +++ b/src/io/digital/DigitalInputManager.cpp @@ -24,7 +24,8 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -DigitalInputManager::DigitalInputManager(UA_NodeId const & node_id) +DigitalInputManager::DigitalInputManager( + UA_NodeId const & node_id) : _node_id{node_id} { /* Nothing happens here. */ @@ -34,7 +35,10 @@ DigitalInputManager::DigitalInputManager(UA_NodeId const & node_id) * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -DigitalInputManager::SharedPtr DigitalInputManager::create(UA_Server * server, UA_NodeId const parent_node_id) +DigitalInputManager::SharedPtr +DigitalInputManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -53,7 +57,7 @@ DigitalInputManager::SharedPtr DigitalInputManager::create(UA_Server * server, U if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "DigitalInputManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -65,13 +69,15 @@ DigitalInputManager::SharedPtr DigitalInputManager::create(UA_Server * server, U * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void DigitalInputManager::add_digital_input(UA_Server * server, - const char * display_name, - DigitalInput::OnReadRequestFunc const on_read_request_func) +void +DigitalInputManager::add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func) { auto const digital_input = DigitalInput::create(server, _node_id, display_name, on_read_request_func); if (!digital_input){ - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalInputManager::add_digital_input: DigitalInput::create(...) failed: returned nullptr"); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInput::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; } _digital_input_list.push_back(digital_input); diff --git a/src/io/digital/DigitalInputManager.h b/src/io/digital/DigitalInputManager.h index a128d08..893eeb4 100644 --- a/src/io/digital/DigitalInputManager.h +++ b/src/io/digital/DigitalInputManager.h @@ -36,13 +36,22 @@ class DigitalInputManager public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); - DigitalInputManager(UA_NodeId const & node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); - void add_digital_input(UA_Server * server, - const char * display_name, - DigitalInput::OnReadRequestFunc const on_read_request_func); + + DigitalInputManager( + UA_NodeId const & node_id); + + + void + add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func); private: diff --git a/src/io/relay/Relay.cpp b/src/io/relay/Relay.cpp index 64dafbb..66e71f5 100644 --- a/src/io/relay/Relay.cpp +++ b/src/io/relay/Relay.cpp @@ -24,13 +24,15 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ -static void relay_on_write_request(UA_Server *server, - const UA_NodeId *sessionId, - void *sessionContext, - const UA_NodeId *nodeid, - void *nodeContext, - const UA_NumericRange *range, - const UA_DataValue *data) +static void +relay_on_write_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) { bool const value = *(UA_Boolean *)(data->value.data) == true; Relay * this_ptr = reinterpret_cast(nodeContext); @@ -41,7 +43,9 @@ static void relay_on_write_request(UA_Server *server, * CTOR/DTOR **************************************************************************************/ -Relay::Relay(UA_NodeId const & node_id, OnSetRelayStateFunc const on_set_relay_state) +Relay::Relay( + UA_NodeId const & node_id, + OnSetRelayStateFunc const on_set_relay_state) : _node_id{node_id} , _on_set_relay_state{on_set_relay_state} { @@ -52,10 +56,12 @@ Relay::Relay(UA_NodeId const & node_id, OnSetRelayStateFunc const on_set_relay_s * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -Relay::SharedPtr Relay::create(UA_Server *server, - UA_NodeId const &parent_node_id, - const char *display_name, - OnSetRelayStateFunc const on_set_relay_state) +Relay::SharedPtr +Relay::create( + UA_Server *server, + UA_NodeId const &parent_node_id, + const char *display_name, + OnSetRelayStateFunc const on_set_relay_state) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -84,7 +90,7 @@ Relay::SharedPtr Relay::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Relay::create: UA_Server_addVariableNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addVariableNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -95,8 +101,7 @@ Relay::SharedPtr Relay::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Relay::create: UA_Server_setNodeContext(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -107,18 +112,20 @@ Relay::SharedPtr Relay::create(UA_Server *server, if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "Relay::create: UA_Server_setVariableNode_valueCallback(...) failed with %s", - UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } -void Relay::onWriteRequest(UA_Server * server, UA_NodeId const * node_id, bool const value) +void +Relay::onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + bool const value) { - /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Relay::onWriteRequest: value = %d", value); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, value); _on_set_relay_state(value); } diff --git a/src/io/relay/Relay.h b/src/io/relay/Relay.h index 837a870..bd3f631 100644 --- a/src/io/relay/Relay.h +++ b/src/io/relay/Relay.h @@ -35,14 +35,25 @@ class Relay typedef std::shared_ptr SharedPtr; typedef std::function OnSetRelayStateFunc; - static SharedPtr create(UA_Server *server, - UA_NodeId const &parent_node_id, - const char *display_name, - OnSetRelayStateFunc const on_set_relay_state); - Relay(UA_NodeId const &node_id, OnSetRelayStateFunc const on_set_relay_state); + static SharedPtr + create( + UA_Server *server, + UA_NodeId const &parent_node_id, + const char *display_name, + OnSetRelayStateFunc const on_set_relay_state); - void onWriteRequest(UA_Server * server, UA_NodeId const * node_id, bool const value); + + Relay( + UA_NodeId const &node_id, + OnSetRelayStateFunc const on_set_relay_state); + + + void + onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + bool const value); private: diff --git a/src/io/relay/RelayManager.cpp b/src/io/relay/RelayManager.cpp index a1d1d95..fb9511e 100644 --- a/src/io/relay/RelayManager.cpp +++ b/src/io/relay/RelayManager.cpp @@ -24,7 +24,8 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -RelayManager::RelayManager(UA_NodeId const & node_id) +RelayManager::RelayManager( + UA_NodeId const & node_id) : _node_id{node_id} { /* Nothing happens here. */ @@ -34,7 +35,10 @@ RelayManager::RelayManager(UA_NodeId const & node_id) * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -RelayManager::SharedPtr RelayManager::create(UA_Server * server, UA_NodeId const parent_node_id) +RelayManager::SharedPtr +RelayManager::create( + UA_Server * server, + UA_NodeId const parent_node_id) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -53,7 +57,7 @@ RelayManager::SharedPtr RelayManager::create(UA_Server * server, UA_NodeId const if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "RelayManager::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -65,13 +69,15 @@ RelayManager::SharedPtr RelayManager::create(UA_Server * server, UA_NodeId const * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void RelayManager::add_relay_output(UA_Server * server, - const char * display_name, - Relay::OnSetRelayStateFunc const on_set_relay_state) +void +RelayManager::add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state) { auto const relay = Relay::create(server, _node_id, display_name, on_set_relay_state); if (!relay) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "RelayManager::add_relay_output: Relay::create(...) failed: returned nullptr"); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: Relay::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; } _relay_list.push_back(relay); diff --git a/src/io/relay/RelayManager.h b/src/io/relay/RelayManager.h index e54e557..a77a0d7 100644 --- a/src/io/relay/RelayManager.h +++ b/src/io/relay/RelayManager.h @@ -36,11 +36,22 @@ class RelayManager public: typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, UA_NodeId const parent_node_id); - RelayManager(UA_NodeId const & node_id); + static SharedPtr + create( + UA_Server * server, + UA_NodeId const parent_node_id); - void add_relay_output(UA_Server * server, const char * display_name, Relay::OnSetRelayStateFunc const on_set_relay_state); + + RelayManager( + UA_NodeId const & node_id); + + + void + add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state); private: From fa8a27788b1a5d28dd0d915c81f3963689e1bfb4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 10:54:10 +0200 Subject: [PATCH 19/29] Simplify API surface of DigitalExpansion classes. --- examples/opcua_server/opcua_server.ino | 27 ++++++++-- src/expansion/DigitalExpansion.cpp | 69 +++++++++++++++----------- src/expansion/DigitalExpansion.h | 24 ++++++--- 3 files changed, 80 insertions(+), 40 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 0f287ec..15bf616 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -249,20 +249,37 @@ void setup() { char analog_in_name[32] = {0}; snprintf(analog_in_name, sizeof(analog_in_name), "Analog Input I%d", d + 1); - exp_dig->analog_input_mgr()->add_analog_input(opc_ua_server, analog_in_name, [i, d]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(d); }); + exp_dig->add_analog_input( + opc_ua_server, + analog_in_name, + [i, d]() + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(d); + }); char digital_in_name[32] = {0}; snprintf(digital_in_name, sizeof(digital_in_name), "Digital Input I%d", d + 1); - exp_dig->digital_input_mgr()->add_digital_input(opc_ua_server, - digital_in_name, - [i, d]() { return reinterpret_cast(OptaController.getExpansionPtr(i))->digitalRead(d, true); }); + exp_dig->add_digital_input( + opc_ua_server, + digital_in_name, + [i, d]() + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->digitalRead(d, true); + }); } + /* Expose mechanical relays via OPC/UA. */ for (uint8_t r = 0; r < OPTA_DIGITAL_OUT_NUM; r++) { char mech_relay_name[32] = {0}; snprintf(mech_relay_name, sizeof(mech_relay_name), "Relay %d", r + 1); - exp_dig->relay_mgr()->add_relay_output(opc_ua_server, mech_relay_name, [i, r](bool const value) { reinterpret_cast(OptaController.getExpansionPtr(i))->digitalWrite(r, value ? HIGH : LOW); }); + exp_dig->add_relay_output( + opc_ua_server, + mech_relay_name, + [i, r](bool const value) + { + reinterpret_cast(OptaController.getExpansionPtr(i))->digitalWrite(r, value ? HIGH : LOW); + }); } } else if (exp_type == EXPANSION_OPTA_ANALOG) diff --git a/src/expansion/DigitalExpansion.cpp b/src/expansion/DigitalExpansion.cpp index 32d01e8..72ee10a 100644 --- a/src/expansion/DigitalExpansion.cpp +++ b/src/expansion/DigitalExpansion.cpp @@ -23,46 +23,57 @@ namespace opcua { /************************************************************************************** - * PUBLIC MEMBER FUNCTIONS + * CTOR/DTOR **************************************************************************************/ -AnalogInputManager::SharedPtr -DigitalExpansion::analog_input_mgr() +DigitalExpansion::DigitalExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name) + : Expansion(server, parent_node_id, display_name, node_name, model_name) + , _analog_input_mgr{opcua::AnalogInputManager::create(_server, _node_id)} + , _digital_input_mgr{opcua::DigitalInputManager::create(_server, _node_id)} + , _relay_mgr{opcua::RelayManager::create(_server, _node_id)} { if (!_analog_input_mgr) - { - _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); - if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _analog_input_mgr; + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_digital_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_relay_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); } -DigitalInputManager::SharedPtr -DigitalExpansion::digital_input_mgr() -{ - if (!_digital_input_mgr) - { - _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); - if (!_digital_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); - } +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ - return _digital_input_mgr; +void +DigitalExpansion::add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func) +{ + _analog_input_mgr->add_analog_input(server, display_name, on_read_request_func); } -RelayManager::SharedPtr -DigitalExpansion::relay_mgr() +void +DigitalExpansion::add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func) { - if (!_relay_mgr) - { - _relay_mgr = opcua::RelayManager::create(_server, _node_id); - if (!_relay_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); - } + _digital_input_mgr->add_digital_input(server, display_name, on_read_request_func); +} - return _relay_mgr; +void +DigitalExpansion::add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state) +{ + _relay_mgr->add_relay_output(server, display_name, on_set_relay_state); } /************************************************************************************** diff --git a/src/expansion/DigitalExpansion.h b/src/expansion/DigitalExpansion.h index 61ffbe2..326bc48 100644 --- a/src/expansion/DigitalExpansion.h +++ b/src/expansion/DigitalExpansion.h @@ -43,14 +43,26 @@ class DigitalExpansion : public Expansion UA_NodeId const parent_node_id, char * display_name, char * node_name, - char * model_name) - : Expansion(server, parent_node_id, display_name, node_name, model_name) - { } + char * model_name); - AnalogInputManager::SharedPtr analog_input_mgr(); - DigitalInputManager::SharedPtr digital_input_mgr(); - RelayManager::SharedPtr relay_mgr(); + void + add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func); + + void + add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func); + + void + add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state); private: From f11a82b10f799cee0b8826c30ed2738daaf5c77e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 12:33:43 +0200 Subject: [PATCH 20/29] Reformatting general Opta public API access to match overall library design. --- examples/opcua_server/opcua_server.ino | 42 ++++++------ src/Opta.cpp | 88 ++++++++++++-------------- src/Opta.h | 29 +++++++-- src/io/led/Led.h | 3 +- src/io/led/LedManager.h | 3 +- 5 files changed, 90 insertions(+), 75 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 15bf616..b727566 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -175,34 +175,34 @@ void setup() } /* Add the various digital input pins. */ - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I1", []() { return arduino_opta_analog_read(A0); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I2", []() { return arduino_opta_analog_read(A1); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I3", []() { return arduino_opta_analog_read(A2); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I4", []() { return arduino_opta_analog_read(A3); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I5", []() { return arduino_opta_analog_read(A4); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I6", []() { return arduino_opta_analog_read(A5); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I7", []() { return arduino_opta_analog_read(A6); }); - opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input I8", []() { return arduino_opta_analog_read(A7); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I1", []() { return arduino_opta_analog_read(A0); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I2", []() { return arduino_opta_analog_read(A1); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I3", []() { return arduino_opta_analog_read(A2); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I4", []() { return arduino_opta_analog_read(A3); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I5", []() { return arduino_opta_analog_read(A4); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I6", []() { return arduino_opta_analog_read(A5); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I7", []() { return arduino_opta_analog_read(A6); }); + opta_opcua->add_analog_input(opc_ua_server, "Analog Input I8", []() { return arduino_opta_analog_read(A7); }); /* Add the various digital input pins. */ - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I1", []() { return arduino_opta_digital_read(A0); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I2", []() { return arduino_opta_digital_read(A1); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I3", []() { return arduino_opta_digital_read(A2); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I4", []() { return arduino_opta_digital_read(A3); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I5", []() { return arduino_opta_digital_read(A4); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I6", []() { return arduino_opta_digital_read(A5); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I7", []() { return arduino_opta_digital_read(A6); }); - opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input I8", []() { return arduino_opta_digital_read(A7); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I1", []() { return arduino_opta_digital_read(A0); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I2", []() { return arduino_opta_digital_read(A1); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I3", []() { return arduino_opta_digital_read(A2); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I4", []() { return arduino_opta_digital_read(A3); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I5", []() { return arduino_opta_digital_read(A4); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I6", []() { return arduino_opta_digital_read(A5); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I7", []() { return arduino_opta_digital_read(A6); }); + opta_opcua->add_digital_input(opc_ua_server, "Digital Input I8", []() { return arduino_opta_digital_read(A7); }); /* Add the various relay outputs. */ - opta_opcua->relay_mgr()->add_relay_output(opc_ua_server, "Relay 1", [](bool const value) { pinMode(RELAY1, OUTPUT); digitalWrite(RELAY1, value); pinMode(LED_D0, OUTPUT); digitalWrite(LED_D0, value); }); - opta_opcua->relay_mgr()->add_relay_output(opc_ua_server, "Relay 2", [](bool const value) { pinMode(RELAY2, OUTPUT); digitalWrite(RELAY2, value); pinMode(LED_D1, OUTPUT); digitalWrite(LED_D1, value);}); - opta_opcua->relay_mgr()->add_relay_output(opc_ua_server, "Relay 3", [](bool const value) { pinMode(RELAY3, OUTPUT); digitalWrite(RELAY3, value); pinMode(LED_D2, OUTPUT); digitalWrite(LED_D2, value);}); - opta_opcua->relay_mgr()->add_relay_output(opc_ua_server, "Relay 4", [](bool const value) { pinMode(RELAY4, OUTPUT); digitalWrite(RELAY4, value); pinMode(LED_D3, OUTPUT); digitalWrite(LED_D3, value);}); + opta_opcua->add_relay_output(opc_ua_server, "Relay 1", [](bool const value) { pinMode(RELAY1, OUTPUT); digitalWrite(RELAY1, value); pinMode(LED_D0, OUTPUT); digitalWrite(LED_D0, value); }); + opta_opcua->add_relay_output(opc_ua_server, "Relay 2", [](bool const value) { pinMode(RELAY2, OUTPUT); digitalWrite(RELAY2, value); pinMode(LED_D1, OUTPUT); digitalWrite(LED_D1, value);}); + opta_opcua->add_relay_output(opc_ua_server, "Relay 3", [](bool const value) { pinMode(RELAY3, OUTPUT); digitalWrite(RELAY3, value); pinMode(LED_D2, OUTPUT); digitalWrite(LED_D2, value);}); + opta_opcua->add_relay_output(opc_ua_server, "Relay 4", [](bool const value) { pinMode(RELAY4, OUTPUT); digitalWrite(RELAY4, value); pinMode(LED_D3, OUTPUT); digitalWrite(LED_D3, value);}); /* Add the various LED outputs. */ if (opta_type == opcua::OptaVariant::Type::WiFi) { - opta_opcua->led_mgr()->add_led_output(opc_ua_server, "User LED", [](bool const value) { pinMode(LEDB, OUTPUT); digitalWrite(LEDB, value); }); + opta_opcua->add_led_output(opc_ua_server, "User LED", [](bool const value) { pinMode(LEDB, OUTPUT); digitalWrite(LEDB, value); }); } /* Check availability of expansion modules. */ diff --git a/src/Opta.cpp b/src/Opta.cpp index a05efcf..0e7c2aa 100644 --- a/src/Opta.cpp +++ b/src/Opta.cpp @@ -26,17 +26,26 @@ namespace opcua Opta::Opta( UA_Server * server, - UA_NodeId const & node_id) + UA_NodeId const & node_id, + OptaVariant::Type const opta_type) : _server{server} , _node_id{node_id} -, _analog_input_mgr{nullptr} -, _digital_input_mgr{nullptr} -, _relay_mgr{nullptr} -, _led_mgr{nullptr} +, _usr_button{opcua::UserButton::create(_server, _node_id)} +, _analog_input_mgr{opcua::AnalogInputManager::create(_server, _node_id)} +, _digital_input_mgr{opcua::DigitalInputManager::create(_server, _node_id)} +, _relay_mgr{opcua::RelayManager::create(_server, _node_id)} +, _led_mgr{(opta_type == OptaVariant::Type::WiFi) ? opcua::LedManager::create(_server, _node_id) : nullptr} { - _usr_button = opcua::UserButton::create(_server, _node_id); if (!_usr_button) UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: UserButton::create(...) failed.", __PRETTY_FUNCTION__); + if (!_analog_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_digital_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); + if (!_relay_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); + if ((opta_type == OptaVariant::Type::WiFi) && !_led_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); } /************************************************************************************** @@ -129,60 +138,45 @@ Opta::create( return nullptr; } - auto const instance_ptr = std::make_shared(server, node_id); + auto const instance_ptr = std::make_shared(server, node_id, opta_type); return instance_ptr; } -AnalogInputManager::SharedPtr -Opta::analog_input_mgr() +void +Opta::add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func) { - if (!_analog_input_mgr) - { - _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); - if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogInputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _analog_input_mgr; + _analog_input_mgr->add_analog_input(server, display_name, on_read_request_func); } -DigitalInputManager::SharedPtr -Opta::digital_input_mgr() +void +Opta::add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func) { - if (!_digital_input_mgr) - { - _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); - if (!_digital_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: DigitalInputManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _digital_input_mgr; + _digital_input_mgr->add_digital_input(server, display_name, on_read_request_func); } -RelayManager::SharedPtr -Opta::relay_mgr() +void +Opta::add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state) { - if (!_relay_mgr) - { - _relay_mgr = opcua::RelayManager::create(_server, _node_id); - if (!_relay_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: RelayManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _relay_mgr; + _relay_mgr->add_relay_output(server, display_name, on_set_relay_state); } -LedManager::SharedPtr -Opta::led_mgr() +void +Opta::add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state) { - if (!_led_mgr) - { - _led_mgr = opcua::LedManager::create(_server, _node_id); - if (!_led_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: LedManager::create(...) failed.", __PRETTY_FUNCTION__); - } - - return _led_mgr; + if (_led_mgr) /* Only available for Arduino Opta WiFi. */ + _led_mgr->add_led_output(server, display_name, on_set_led_state); } /************************************************************************************** diff --git a/src/Opta.h b/src/Opta.h index 5f9962d..112a1a8 100644 --- a/src/Opta.h +++ b/src/Opta.h @@ -50,14 +50,33 @@ class Opta Opta( UA_Server * server, - UA_NodeId const & node_id); + UA_NodeId const & node_id, + OptaVariant::Type const opta_type); + + void + add_analog_input( + UA_Server * server, + const char * display_name, + AnalogInput::OnReadRequestFunc const on_read_request_func); - AnalogInputManager::SharedPtr analog_input_mgr(); - DigitalInputManager::SharedPtr digital_input_mgr(); - RelayManager::SharedPtr relay_mgr(); - LedManager::SharedPtr led_mgr(); + void + add_digital_input( + UA_Server * server, + const char * display_name, + DigitalInput::OnReadRequestFunc const on_read_request_func); + void + add_relay_output( + UA_Server * server, + const char * display_name, + Relay::OnSetRelayStateFunc const on_set_relay_state); + + void + add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state); [[nodiscard]] UA_NodeId node_id() const { return _node_id; } diff --git a/src/io/led/Led.h b/src/io/led/Led.h index 6c9b62a..dfb0126 100644 --- a/src/io/led/Led.h +++ b/src/io/led/Led.h @@ -49,7 +49,8 @@ class Led OnSetLedStateFunc const on_set_led_state); - void onWriteRequest( + void + onWriteRequest( UA_Server * server, UA_NodeId const * node_id, bool const value); diff --git a/src/io/led/LedManager.h b/src/io/led/LedManager.h index f5b0260..ad91493 100644 --- a/src/io/led/LedManager.h +++ b/src/io/led/LedManager.h @@ -45,7 +45,8 @@ class LedManager LedManager(UA_NodeId const & node_id); - void add_led_output( + void + add_led_output( UA_Server * server, const char * display_name, Led::OnSetLedStateFunc const on_set_led_state); From 40b778768c6752640dd6c1b5b236c5ee03a01747 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 3 Sep 2024 12:44:41 +0200 Subject: [PATCH 21/29] Read back configured DAC value when queried via OPC/UA. --- examples/opcua_server/opcua_server.ino | 6 +++- src/expansion/AnalogExpansion.cpp | 3 +- src/expansion/AnalogExpansion.h | 1 + src/io/analog/AnalogOutput.cpp | 40 ++++++++++++++++++++++++-- src/io/analog/AnalogOutput.h | 14 +++++++-- src/io/analog/AnalogOutputManager.cpp | 3 +- src/io/analog/AnalogOutputManager.h | 1 + 7 files changed, 60 insertions(+), 8 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index b727566..12f200b 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -334,9 +334,13 @@ void setup() exp_analog->add_analog_output( opc_ua_server, analog_out_name, + [i, a]() + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); + }, [i, a](float const voltage) { - return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); + reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); }); output_num++; } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 47e42af..4ea0e0a 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -81,9 +81,10 @@ void AnalogExpansion::add_analog_output( UA_Server * server, const char * display_name, + AnalogOutput::OnReadRequestFunc const on_read_request, AnalogOutput::OnWriteRequestFunc const on_write_request_func) { - _analog_output_mgr->add_analog_output(server, display_name, on_write_request_func); + _analog_output_mgr->add_analog_output(server, display_name, on_read_request, on_write_request_func); } void diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index d839af1..244659d 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -64,6 +64,7 @@ class AnalogExpansion : public Expansion add_analog_output( UA_Server * server, const char * display_name, + AnalogOutput::OnReadRequestFunc const on_read_request, AnalogOutput::OnWriteRequestFunc const on_write_request_func); void diff --git a/src/io/analog/AnalogOutput.cpp b/src/io/analog/AnalogOutput.cpp index 5b76ffe..2df903c 100644 --- a/src/io/analog/AnalogOutput.cpp +++ b/src/io/analog/AnalogOutput.cpp @@ -24,6 +24,20 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ +static void +analog_input_on_read_request( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + AnalogOutput * this_ptr = reinterpret_cast(nodeContext); + this_ptr->onReadRequest(server, nodeid); +} + static void analog_output_on_write_request( UA_Server *server, @@ -45,8 +59,10 @@ analog_output_on_write_request( AnalogOutput::AnalogOutput( UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request, OnWriteRequestFunc const on_write_request) : _node_id{node_id} +, _on_read_request{on_read_request} , _on_write_request{on_write_request} { @@ -61,13 +77,14 @@ AnalogOutput::create( UA_Server * server, UA_NodeId const & parent_node_id, const char * display_name, + OnReadRequestFunc const on_read_request, OnWriteRequestFunc const on_write_request) { UA_StatusCode rc = UA_STATUSCODE_GOOD; UA_VariableAttributes analog_output_value_attr = UA_VariableAttributes_default; - UA_Float analog_output_value = 0.; + UA_Float analog_output_value = on_read_request(); UA_Variant_setScalar(&analog_output_value_attr.value, &analog_output_value, &UA_TYPES[UA_TYPES_FLOAT]); analog_output_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); @@ -95,7 +112,7 @@ AnalogOutput::create( } /* Create an instance of AnalogOutput here. */ - auto const instance_ptr = std::make_shared(node_id, on_write_request); + auto const instance_ptr = std::make_shared(node_id, on_read_request, on_write_request); rc = UA_Server_setNodeContext(server, node_id, reinterpret_cast(instance_ptr.get())); if (UA_StatusCode_isBad(rc)) @@ -106,7 +123,7 @@ AnalogOutput::create( } UA_ValueCallback callback; - callback.onRead = NULL; + callback.onRead = analog_input_on_read_request; callback.onWrite = analog_output_on_write_request; rc = UA_Server_setVariableNode_valueCallback(server, node_id, callback); if (UA_StatusCode_isBad(rc)) @@ -119,6 +136,23 @@ AnalogOutput::create( return instance_ptr; } +void +AnalogOutput::onReadRequest( + UA_Server * server, + UA_NodeId const * node_id) +{ + /* Obtain the value of the analog input pin. */ + float const in_x_val = _on_read_request(); + /* Update the variable node. */ + UA_Float in_x_val_opcua_value = in_x_val; + UA_Variant in_x_val_opcua_variant; + UA_Variant_init(&in_x_val_opcua_variant); + UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_FLOAT]); + UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); + /* Some debug output. */ + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %f", __PRETTY_FUNCTION__, in_x_val); +} + void AnalogOutput::onWriteRequest( UA_Server * server, diff --git a/src/io/analog/AnalogOutput.h b/src/io/analog/AnalogOutput.h index ed98df7..0b1332e 100644 --- a/src/io/analog/AnalogOutput.h +++ b/src/io/analog/AnalogOutput.h @@ -35,6 +35,7 @@ class AnalogOutput { public: typedef std::shared_ptr SharedPtr; + typedef std::function OnReadRequestFunc; typedef std::function OnWriteRequestFunc; @@ -43,15 +44,23 @@ class AnalogOutput UA_Server * server, UA_NodeId const & parent_node_id, const char * display_name, + OnReadRequestFunc const on_read_request, OnWriteRequestFunc const on_write_request); AnalogOutput( UA_NodeId const & node_id, + OnReadRequestFunc const on_read_request, OnWriteRequestFunc const on_write_request); - void onWriteRequest( + void + onReadRequest( + UA_Server * server, + UA_NodeId const * node_id); + + void + onWriteRequest( UA_Server * server, UA_NodeId const * node_id, float const voltage); @@ -59,7 +68,8 @@ class AnalogOutput private: UA_NodeId _node_id; - OnWriteRequestFunc _on_write_request; + OnReadRequestFunc const _on_read_request; + OnWriteRequestFunc const _on_write_request; }; /************************************************************************************** diff --git a/src/io/analog/AnalogOutputManager.cpp b/src/io/analog/AnalogOutputManager.cpp index 39d795c..ea31431 100644 --- a/src/io/analog/AnalogOutputManager.cpp +++ b/src/io/analog/AnalogOutputManager.cpp @@ -73,9 +73,10 @@ void AnalogOutputManager::add_analog_output( UA_Server * server, const char * display_name, + AnalogOutput::OnReadRequestFunc const on_read_request, AnalogOutput::OnWriteRequestFunc const on_write_request_func) { - auto const analog_output = AnalogOutput::create(server, _node_id, display_name, on_write_request_func); + auto const analog_output = AnalogOutput::create(server, _node_id, display_name, on_read_request, on_write_request_func); if (!analog_output) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: AnalogOutput::create(...) failed: returned nullptr", __PRETTY_FUNCTION__); return; diff --git a/src/io/analog/AnalogOutputManager.h b/src/io/analog/AnalogOutputManager.h index c80ffb2..f025fed 100644 --- a/src/io/analog/AnalogOutputManager.h +++ b/src/io/analog/AnalogOutputManager.h @@ -51,6 +51,7 @@ class AnalogOutputManager add_analog_output( UA_Server * server, const char * display_name, + AnalogOutput::OnReadRequestFunc const on_read_request, AnalogOutput::OnWriteRequestFunc const on_write_request_func); From 096b4a5fc133187fe9f853089229a335dcbad9c0 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 Sep 2024 06:47:42 +0200 Subject: [PATCH 22/29] Introduce high level PWM1-n object node to group period and pulse width as variable nodes beneath. --- src/io/pwm/PwmOutput.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp index 0f86446..3fdd52f 100644 --- a/src/io/pwm/PwmOutput.cpp +++ b/src/io/pwm/PwmOutput.cpp @@ -82,6 +82,25 @@ PwmOutput::create( { UA_StatusCode rc = UA_STATUSCODE_GOOD; + UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); + UA_NodeId pwm_obj_node_id; + rc = UA_Server_addObjectNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_QUALIFIEDNAME(1, (char *)display_name), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), + oAttr, + NULL, + &pwm_obj_node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_addObjectNode(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + UA_VariableAttributes pwm_out_period_value_attr = UA_VariableAttributes_default; UA_Boolean pwm_output_period_value = 0; @@ -97,7 +116,7 @@ PwmOutput::create( UA_NodeId node_id; rc = UA_Server_addVariableNode(server, UA_NODEID_NULL, - parent_node_id, + pwm_obj_node_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Value"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), From d54d655eca558578e0d844e7c068f88890c5f5c3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 Sep 2024 07:17:47 +0200 Subject: [PATCH 23/29] Add function to obtain the current value of the PWM period. --- examples/opcua_server/opcua_server.ino | 4 ++ src/expansion/AnalogExpansion.cpp | 5 +- src/expansion/AnalogExpansion.h | 3 +- src/io/pwm/PwmOutput.cpp | 72 +++++++++++++++++++------- src/io/pwm/PwmOutput.h | 19 +++++-- src/io/pwm/PwmOutputManager.cpp | 5 +- src/io/pwm/PwmOutputManager.h | 3 +- 7 files changed, 81 insertions(+), 30 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 12f200b..d2f788e 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -357,6 +357,10 @@ void setup() [i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms) { reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms); + }, + [i, p](void) -> uint32_t + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->getPwmPeriod(p); }); pwm_output_num++; } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 4ea0e0a..bde7c6d 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -91,9 +91,10 @@ void AnalogExpansion::add_pwm_output( UA_Server * server, const char * display_name, - PwmOutput::SetPwmFunc const set_pwm_func) + PwmOutput::SetPwmFunc const set_pwm_func, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func) { - _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func); + _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func); } void diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 244659d..3676ace 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -71,7 +71,8 @@ class AnalogExpansion : public Expansion add_pwm_output( UA_Server * server, const char * display_name, - PwmOutput::SetPwmFunc const set_pwm_func); + PwmOutput::SetPwmFunc const set_pwm_func, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func); void add_led_output( diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp index 3fdd52f..00031ef 100644 --- a/src/io/pwm/PwmOutput.cpp +++ b/src/io/pwm/PwmOutput.cpp @@ -24,6 +24,20 @@ namespace opcua * FUNCTION DEFINITION **************************************************************************************/ +static void +pwm_output_on_read_request_pwm_period( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + PwmOutput * this_ptr = reinterpret_cast(nodeContext); + this_ptr->onReadRequestPwmPeriod(server, nodeid); +} + static void pwm_output_on_write_request_pwm_period( UA_Server *server, @@ -59,10 +73,12 @@ pwm_output_on_write_request_pwm_pulse_width( **************************************************************************************/ PwmOutput::PwmOutput( - UA_NodeId const & node_id, - SetPwmFunc const set_pwm_func) - : _node_id{node_id} + UA_NodeId const & pwm_period_node_id, + SetPwmFunc const set_pwm_func, + GetPwmPeriodFunc const get_pwm_period_func) + : _pwm_period_node_id{pwm_period_node_id} , _set_pwm_func{set_pwm_func} + , _get_pwm_period_func{get_pwm_period_func} , _pwm_period_ms{0} , _pwm_pulse_width_ms{0} { @@ -78,7 +94,8 @@ PwmOutput::create( UA_Server * server, UA_NodeId const & parent_node_id, const char * display_name, - SetPwmFunc const set_pwm_func) + SetPwmFunc const set_pwm_func, + GetPwmPeriodFunc const get_pwm_period_func) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -103,26 +120,26 @@ PwmOutput::create( UA_VariableAttributes pwm_out_period_value_attr = UA_VariableAttributes_default; - UA_Boolean pwm_output_period_value = 0; + UA_Boolean pwm_output_period_value = get_pwm_period_func(); UA_Variant_setScalar(&pwm_out_period_value_attr.value, &pwm_output_period_value, &UA_TYPES[UA_TYPES_UINT32]); - pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)display_name); + pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Period / ms"); pwm_out_period_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; pwm_out_period_value_attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_STATUSWRITE | UA_ACCESSLEVELMASK_TIMESTAMPWRITE; /* Status and timestamp write access necessary for opcua-client. */ - UA_NodeId node_id; + UA_NodeId pwm_period_node_id; rc = UA_Server_addVariableNode(server, UA_NODEID_NULL, pwm_obj_node_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), - UA_QUALIFIEDNAME(1, "Value"), + UA_QUALIFIEDNAME(1, "PWM Period / ms"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), pwm_out_period_value_attr, NULL, - &node_id); + &pwm_period_node_id); if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, @@ -131,9 +148,9 @@ PwmOutput::create( } /* Create an instance of AnalogOutput here. */ - auto const instance_ptr = std::make_shared(node_id, set_pwm_func); + auto const instance_ptr = std::make_shared(pwm_period_node_id, set_pwm_func, get_pwm_period_func); - rc = UA_Server_setNodeContext(server, node_id, reinterpret_cast(instance_ptr.get())); + rc = UA_Server_setNodeContext(server, pwm_period_node_id, reinterpret_cast(instance_ptr.get())); if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, @@ -141,28 +158,45 @@ PwmOutput::create( return nullptr; } - UA_ValueCallback callback; - callback.onRead = NULL; - callback.onWrite = pwm_output_on_write_request_pwm_period; - rc = UA_Server_setVariableNode_valueCallback(server, node_id, callback); + UA_ValueCallback pwm_period_callback; + pwm_period_callback.onRead = pwm_output_on_read_request_pwm_period; + pwm_period_callback.onWrite = pwm_output_on_write_request_pwm_period; + rc = UA_Server_setVariableNode_valueCallback(server, pwm_period_node_id, pwm_period_callback); if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "%s: UA_Server_setVariableNode_valueCallback(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + "%s: UA_Server_setVariableNode_valueCallback(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } return instance_ptr; } +void +PwmOutput::onReadRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * node_id) +{ + /* Obtain the value of the analog input pin. */ + uint32_t const in_x_val = _get_pwm_period_func(); + /* Update the variable node. */ + UA_UInt32 in_x_val_opcua_value = in_x_val; + UA_Variant in_x_val_opcua_variant; + UA_Variant_init(&in_x_val_opcua_variant); + UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); + UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); + /* Some debug output. */ + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, in_x_val); +} + void PwmOutput::onWriteRequestPwmPeriod( UA_Server * server, - UA_NodeId const * node_id, + UA_NodeId const * pwm_period_node_id, uint32_t const pwm_period_ms) { _pwm_period_ms = pwm_period_ms; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms); _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); } @@ -173,7 +207,7 @@ PwmOutput::onWriteRequestPwmPulseWidth( uint32_t const pwm_pulse_width_ms) { _pwm_pulse_width_ms = pwm_pulse_width_ms; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_pulse_width_ms); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms); _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); } diff --git a/src/io/pwm/PwmOutput.h b/src/io/pwm/PwmOutput.h index 147a63f..84b5ae9 100644 --- a/src/io/pwm/PwmOutput.h +++ b/src/io/pwm/PwmOutput.h @@ -36,6 +36,7 @@ class PwmOutput public: typedef std::shared_ptr SharedPtr; typedef std::function SetPwmFunc; + typedef std::function GetPwmPeriodFunc; static SharedPtr @@ -43,18 +44,25 @@ class PwmOutput UA_Server * server, UA_NodeId const & parent_node_id, const char * display_name, - SetPwmFunc const set_pwm_func); + SetPwmFunc const set_pwm_func, + GetPwmPeriodFunc const get_pwm_period_func); PwmOutput( - UA_NodeId const & node_id, - SetPwmFunc const set_pwm_func); + UA_NodeId const & pwm_period_node_id, + SetPwmFunc const set_pwm_func, + GetPwmPeriodFunc const get_pwm_period_func); + void + onReadRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * node_id); + void onWriteRequestPwmPeriod( UA_Server * server, - UA_NodeId const * node_id, + UA_NodeId const * pwm_period_node_id, uint32_t const pwm_period_ms); void @@ -65,8 +73,9 @@ class PwmOutput private: - UA_NodeId _node_id; + UA_NodeId _pwm_period_node_id; SetPwmFunc const _set_pwm_func; + GetPwmPeriodFunc const _get_pwm_period_func; uint32_t _pwm_period_ms, _pwm_pulse_width_ms; }; diff --git a/src/io/pwm/PwmOutputManager.cpp b/src/io/pwm/PwmOutputManager.cpp index 87decc0..bd4e01a 100644 --- a/src/io/pwm/PwmOutputManager.cpp +++ b/src/io/pwm/PwmOutputManager.cpp @@ -73,9 +73,10 @@ void PwmOutputManager::add_pwm_output( UA_Server * server, const char * display_name, - PwmOutput::SetPwmFunc const set_pwm_func) + PwmOutput::SetPwmFunc const set_pwm_func, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func) { - auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func); + auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func, get_pwm_period_func); if (!pwm_output) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, diff --git a/src/io/pwm/PwmOutputManager.h b/src/io/pwm/PwmOutputManager.h index 217736a..62ee8d2 100644 --- a/src/io/pwm/PwmOutputManager.h +++ b/src/io/pwm/PwmOutputManager.h @@ -50,7 +50,8 @@ class PwmOutputManager add_pwm_output( UA_Server * server, const char * display_name, - PwmOutput::SetPwmFunc const set_pwm_func); + PwmOutput::SetPwmFunc const set_pwm_func, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func); private: From 0f8ef0fa6241a1f78dff80af7382d75a36cb534d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 Sep 2024 07:23:59 +0200 Subject: [PATCH 24/29] Fix: we need to supply the direct channel number as a parameter (1, 2, 3, 4, ...) not OA_PWM_CH_FIRST ... (8, 9, 10, 11, ...) because that's what getPwmPeriod expects. --- examples/opcua_server/opcua_server.ino | 2 +- src/io/pwm/PwmOutput.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index d2f788e..9a12246 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -360,7 +360,7 @@ void setup() }, [i, p](void) -> uint32_t { - return reinterpret_cast(OptaController.getExpansionPtr(i))->getPwmPeriod(p); + return reinterpret_cast(OptaController.getExpansionPtr(i))->getPwmPeriod(p - OA_PWM_CH_FIRST); }); pwm_output_num++; } diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp index 00031ef..d1a5c92 100644 --- a/src/io/pwm/PwmOutput.cpp +++ b/src/io/pwm/PwmOutput.cpp @@ -186,7 +186,7 @@ PwmOutput::onReadRequestPwmPeriod( UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: value = %d", __PRETTY_FUNCTION__, in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms", __PRETTY_FUNCTION__, in_x_val); } void From 3ee5179b857fad9236777eed2337c8cbf8300945 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 Sep 2024 08:54:14 +0200 Subject: [PATCH 25/29] Implement reading of PWM pulse width from Arduino_Opta_Blueprint. --- examples/opcua_server/opcua_server.ino | 8 +- src/expansion/AnalogExpansion.cpp | 5 +- src/expansion/AnalogExpansion.h | 3 +- src/io/pwm/PwmOutput.cpp | 137 ++++++++++++++++++++----- src/io/pwm/PwmOutput.h | 21 +++- src/io/pwm/PwmOutputManager.cpp | 5 +- src/io/pwm/PwmOutputManager.h | 3 +- 7 files changed, 142 insertions(+), 40 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 9a12246..0456ff5 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -354,13 +354,17 @@ void setup() exp_analog->add_pwm_output( opc_ua_server, pwm_out_name, - [i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms) + [i, p](uint32_t const pwm_period_us, uint32_t const pwm_pulse_width_us) { - reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms); + reinterpret_cast(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_us, pwm_pulse_width_us); }, [i, p](void) -> uint32_t { return reinterpret_cast(OptaController.getExpansionPtr(i))->getPwmPeriod(p - OA_PWM_CH_FIRST); + }, + [i, p](void) -> uint32_t + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->getPwmPulse(p - OA_PWM_CH_FIRST); }); pwm_output_num++; } diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index bde7c6d..65c92b4 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -92,9 +92,10 @@ AnalogExpansion::add_pwm_output( UA_Server * server, const char * display_name, PwmOutput::SetPwmFunc const set_pwm_func, - PwmOutput::GetPwmPeriodFunc const get_pwm_period_func) + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func) { - _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func); + _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func); } void diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 3676ace..01ca38a 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -72,7 +72,8 @@ class AnalogExpansion : public Expansion UA_Server * server, const char * display_name, PwmOutput::SetPwmFunc const set_pwm_func, - PwmOutput::GetPwmPeriodFunc const get_pwm_period_func); + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func); void add_led_output( diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp index d1a5c92..83d41f5 100644 --- a/src/io/pwm/PwmOutput.cpp +++ b/src/io/pwm/PwmOutput.cpp @@ -49,8 +49,22 @@ pwm_output_on_write_request_pwm_period( const UA_DataValue *data) { PwmOutput * this_ptr = reinterpret_cast(nodeContext); - uint32_t const pwm_period_ms = *(UA_UInt32 *)(data->value.data); - this_ptr->onWriteRequestPwmPeriod(server, nodeid, pwm_period_ms); + uint32_t const pwm_period_us = *(UA_UInt32 *)(data->value.data); + this_ptr->onWriteRequestPwmPeriod(server, nodeid, pwm_period_us); +} + +static void +pwm_output_on_read_request_pwm_pulse_width( + UA_Server *server, + const UA_NodeId *sessionId, + void *sessionContext, + const UA_NodeId *nodeid, + void *nodeContext, + const UA_NumericRange *range, + const UA_DataValue *data) +{ + PwmOutput * this_ptr = reinterpret_cast(nodeContext); + this_ptr->onReadRequestPwmPulseWidth(server, nodeid); } static void @@ -64,8 +78,8 @@ pwm_output_on_write_request_pwm_pulse_width( const UA_DataValue *data) { PwmOutput * this_ptr = reinterpret_cast(nodeContext); - uint32_t const pwm_pulse_width_ms = *(UA_UInt32 *)(data->value.data); - this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_ms); + uint32_t const pwm_pulse_width_us = *(UA_UInt32 *)(data->value.data); + this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_us); } /************************************************************************************** @@ -74,13 +88,17 @@ pwm_output_on_write_request_pwm_pulse_width( PwmOutput::PwmOutput( UA_NodeId const & pwm_period_node_id, + UA_NodeId const & pwm_pulse_width_node_id, SetPwmFunc const set_pwm_func, - GetPwmPeriodFunc const get_pwm_period_func) + GetPwmPeriodFunc const get_pwm_period_func, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func) : _pwm_period_node_id{pwm_period_node_id} + , _pwm_pulse_width_node_id{pwm_pulse_width_node_id} , _set_pwm_func{set_pwm_func} , _get_pwm_period_func{get_pwm_period_func} - , _pwm_period_ms{0} - , _pwm_pulse_width_ms{0} + , _get_pwm_pulse_width_func{get_pwm_pulse_width_func} + , _pwm_period_us{0} + , _pwm_pulse_width_us{0} { } @@ -95,7 +113,8 @@ PwmOutput::create( UA_NodeId const & parent_node_id, const char * display_name, SetPwmFunc const set_pwm_func, - GetPwmPeriodFunc const get_pwm_period_func) + GetPwmPeriodFunc const get_pwm_period_func, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func) { UA_StatusCode rc = UA_STATUSCODE_GOOD; @@ -123,7 +142,7 @@ PwmOutput::create( UA_Boolean pwm_output_period_value = get_pwm_period_func(); UA_Variant_setScalar(&pwm_out_period_value_attr.value, &pwm_output_period_value, &UA_TYPES[UA_TYPES_UINT32]); - pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Period / ms"); + pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Period / us"); pwm_out_period_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; pwm_out_period_value_attr.accessLevel = UA_ACCESSLEVELMASK_READ | @@ -135,7 +154,7 @@ PwmOutput::create( UA_NODEID_NULL, pwm_obj_node_id, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), - UA_QUALIFIEDNAME(1, "PWM Period / ms"), + UA_QUALIFIEDNAME(1, "pwm_period_us"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), pwm_out_period_value_attr, NULL, @@ -147,25 +166,72 @@ PwmOutput::create( return nullptr; } - /* Create an instance of AnalogOutput here. */ - auto const instance_ptr = std::make_shared(pwm_period_node_id, set_pwm_func, get_pwm_period_func); + UA_ValueCallback pwm_period_callback; + pwm_period_callback.onRead = pwm_output_on_read_request_pwm_period; + pwm_period_callback.onWrite = pwm_output_on_write_request_pwm_period; + rc = UA_Server_setVariableNode_valueCallback(server, pwm_period_node_id, pwm_period_callback); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_setVariableNode_valueCallback(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + UA_VariableAttributes pwm_out_pulse_width_value_attr = UA_VariableAttributes_default; + + UA_Boolean pwm_output_pulse_width_value = get_pwm_pulse_width_func(); + UA_Variant_setScalar(&pwm_out_pulse_width_value_attr.value, &pwm_output_pulse_width_value, &UA_TYPES[UA_TYPES_UINT32]); + + pwm_out_pulse_width_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Pulse Width / us"); + pwm_out_pulse_width_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; + pwm_out_pulse_width_value_attr.accessLevel = + UA_ACCESSLEVELMASK_READ | + UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_STATUSWRITE | + UA_ACCESSLEVELMASK_TIMESTAMPWRITE; /* Status and timestamp write access necessary for opcua-client. */ + + UA_NodeId pwm_pulse_width_node_id; + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + pwm_obj_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "pwm_pulse_width_us"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + pwm_out_pulse_width_value_attr, + NULL, + &pwm_pulse_width_node_id); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + UA_ValueCallback pwm_pulse_width_callback; + pwm_pulse_width_callback.onRead = pwm_output_on_read_request_pwm_pulse_width; + pwm_pulse_width_callback.onWrite = pwm_output_on_write_request_pwm_pulse_width; + rc = UA_Server_setVariableNode_valueCallback(server, pwm_pulse_width_node_id, pwm_pulse_width_callback); + if (UA_StatusCode_isBad(rc)) + { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, + "%s: UA_Server_setVariableNode_valueCallback(pwm_pulse_width_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + auto const instance_ptr = std::make_shared(pwm_period_node_id, pwm_pulse_width_node_id, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func); rc = UA_Server_setNodeContext(server, pwm_period_node_id, reinterpret_cast(instance_ptr.get())); if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } - UA_ValueCallback pwm_period_callback; - pwm_period_callback.onRead = pwm_output_on_read_request_pwm_period; - pwm_period_callback.onWrite = pwm_output_on_write_request_pwm_period; - rc = UA_Server_setVariableNode_valueCallback(server, pwm_period_node_id, pwm_period_callback); + rc = UA_Server_setNodeContext(server, pwm_pulse_width_node_id, reinterpret_cast(instance_ptr.get())); if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "%s: UA_Server_setVariableNode_valueCallback(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + "%s: UA_Server_setNodeContext(pwm_pulse_width_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); return nullptr; } @@ -186,29 +252,46 @@ PwmOutput::onReadRequestPwmPeriod( UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms", __PRETTY_FUNCTION__, in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us", __PRETTY_FUNCTION__, in_x_val); } void PwmOutput::onWriteRequestPwmPeriod( UA_Server * server, UA_NodeId const * pwm_period_node_id, - uint32_t const pwm_period_ms) + uint32_t const pwm_period_us) +{ + _pwm_period_us = pwm_period_us; + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us, pulse width = %d us", __PRETTY_FUNCTION__, _pwm_period_us, _pwm_pulse_width_us); + _set_pwm_func(_pwm_period_us, _pwm_pulse_width_us); +} + +void +PwmOutput::onReadRequestPwmPulseWidth( + UA_Server * server, + UA_NodeId const * node_id) { - _pwm_period_ms = pwm_period_ms; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms); - _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); + /* Obtain the value of the analog input pin. */ + uint32_t const in_x_val = _get_pwm_pulse_width_func(); + /* Update the variable node. */ + UA_UInt32 in_x_val_opcua_value = in_x_val; + UA_Variant in_x_val_opcua_variant; + UA_Variant_init(&in_x_val_opcua_variant); + UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); + UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); + /* Some debug output. */ + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d us", __PRETTY_FUNCTION__, in_x_val); } void PwmOutput::onWriteRequestPwmPulseWidth( UA_Server * server, UA_NodeId const * node_id, - uint32_t const pwm_pulse_width_ms) + uint32_t const pwm_pulse_width_us) { - _pwm_pulse_width_ms = pwm_pulse_width_ms; - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms); - _set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms); + _pwm_pulse_width_us = pwm_pulse_width_us; + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us, pulse width = %d us", __PRETTY_FUNCTION__, _pwm_period_us, _pwm_pulse_width_us); + _set_pwm_func(_pwm_period_us, _pwm_pulse_width_us); } /************************************************************************************** diff --git a/src/io/pwm/PwmOutput.h b/src/io/pwm/PwmOutput.h index 84b5ae9..b17b4e4 100644 --- a/src/io/pwm/PwmOutput.h +++ b/src/io/pwm/PwmOutput.h @@ -37,6 +37,7 @@ class PwmOutput typedef std::shared_ptr SharedPtr; typedef std::function SetPwmFunc; typedef std::function GetPwmPeriodFunc; + typedef std::function GetPwmPulseWidthFunc; static SharedPtr @@ -45,13 +46,16 @@ class PwmOutput UA_NodeId const & parent_node_id, const char * display_name, SetPwmFunc const set_pwm_func, - GetPwmPeriodFunc const get_pwm_period_func); + GetPwmPeriodFunc const get_pwm_period_func, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func); PwmOutput( UA_NodeId const & pwm_period_node_id, + UA_NodeId const & pwm_pulse_width_node_id, SetPwmFunc const set_pwm_func, - GetPwmPeriodFunc const get_pwm_period_func); + GetPwmPeriodFunc const get_pwm_period_func, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func); void @@ -63,20 +67,27 @@ class PwmOutput onWriteRequestPwmPeriod( UA_Server * server, UA_NodeId const * pwm_period_node_id, - uint32_t const pwm_period_ms); + uint32_t const pwm_period_us); + + void + onReadRequestPwmPulseWidth( + UA_Server * server, + UA_NodeId const * node_id); void onWriteRequestPwmPulseWidth( UA_Server * server, UA_NodeId const * node_id, - uint32_t const pwm_pulse_width_ms); + uint32_t const pwm_pulse_width_us); private: UA_NodeId _pwm_period_node_id; + UA_NodeId _pwm_pulse_width_node_id; SetPwmFunc const _set_pwm_func; GetPwmPeriodFunc const _get_pwm_period_func; - uint32_t _pwm_period_ms, _pwm_pulse_width_ms; + GetPwmPulseWidthFunc const _get_pwm_pulse_width_func; + uint32_t _pwm_period_us, _pwm_pulse_width_us; }; /************************************************************************************** diff --git a/src/io/pwm/PwmOutputManager.cpp b/src/io/pwm/PwmOutputManager.cpp index bd4e01a..0ada80b 100644 --- a/src/io/pwm/PwmOutputManager.cpp +++ b/src/io/pwm/PwmOutputManager.cpp @@ -74,9 +74,10 @@ PwmOutputManager::add_pwm_output( UA_Server * server, const char * display_name, PwmOutput::SetPwmFunc const set_pwm_func, - PwmOutput::GetPwmPeriodFunc const get_pwm_period_func) + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func) { - auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func, get_pwm_period_func); + auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func); if (!pwm_output) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, diff --git a/src/io/pwm/PwmOutputManager.h b/src/io/pwm/PwmOutputManager.h index 62ee8d2..7ff5fd3 100644 --- a/src/io/pwm/PwmOutputManager.h +++ b/src/io/pwm/PwmOutputManager.h @@ -51,7 +51,8 @@ class PwmOutputManager UA_Server * server, const char * display_name, PwmOutput::SetPwmFunc const set_pwm_func, - PwmOutput::GetPwmPeriodFunc const get_pwm_period_func); + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func); private: From ff9e3032a683d8560f4fe14b1518d8434d0a238c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 4 Sep 2024 08:57:33 +0200 Subject: [PATCH 26/29] Fix: also update state of internal member variables when reading back. --- src/io/pwm/PwmOutput.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp index 83d41f5..7060439 100644 --- a/src/io/pwm/PwmOutput.cpp +++ b/src/io/pwm/PwmOutput.cpp @@ -244,15 +244,15 @@ PwmOutput::onReadRequestPwmPeriod( UA_NodeId const * node_id) { /* Obtain the value of the analog input pin. */ - uint32_t const in_x_val = _get_pwm_period_func(); + _pwm_period_us = _get_pwm_period_func(); /* Update the variable node. */ - UA_UInt32 in_x_val_opcua_value = in_x_val; + UA_UInt32 in_x_val_opcua_value = _pwm_period_us; UA_Variant in_x_val_opcua_variant; UA_Variant_init(&in_x_val_opcua_variant); UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us", __PRETTY_FUNCTION__, in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us", __PRETTY_FUNCTION__, _pwm_period_us); } void @@ -272,15 +272,15 @@ PwmOutput::onReadRequestPwmPulseWidth( UA_NodeId const * node_id) { /* Obtain the value of the analog input pin. */ - uint32_t const in_x_val = _get_pwm_pulse_width_func(); + _pwm_pulse_width_us = _get_pwm_pulse_width_func(); /* Update the variable node. */ - UA_UInt32 in_x_val_opcua_value = in_x_val; + UA_UInt32 in_x_val_opcua_value = _pwm_pulse_width_us; UA_Variant in_x_val_opcua_variant; UA_Variant_init(&in_x_val_opcua_variant); UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]); UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant); /* Some debug output. */ - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d us", __PRETTY_FUNCTION__, in_x_val); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d us", __PRETTY_FUNCTION__, _pwm_pulse_width_us); } void From f6478942d264e569b845fe7ea8d06623cf896abb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 5 Sep 2024 09:11:33 +0200 Subject: [PATCH 27/29] Eliminate "node_id" API - as it only makes sense for the ModBus demonstration - and not even there much. --- examples/opcua_server/opcua_server.ino | 2 +- src/Opta.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 0456ff5..ab92976 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -397,7 +397,7 @@ void setup() UA_NodeId modbus_md02_node_id; rc = UA_Server_addObjectNode(opc_ua_server, UA_NODEID_NULL, - opta_opcua->node_id(), + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "ModbusRs485Md02"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), diff --git a/src/Opta.h b/src/Opta.h index 112a1a8..21cb80e 100644 --- a/src/Opta.h +++ b/src/Opta.h @@ -78,8 +78,6 @@ class Opta const char * display_name, Led::OnSetLedStateFunc const on_set_led_state); - [[nodiscard]] UA_NodeId node_id() const { return _node_id; } - private: UA_Server * _server; From c726189cfaa95e016f2cce71c1493a85320ea1e6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 5 Sep 2024 09:17:07 +0200 Subject: [PATCH 28/29] Document support for various Arduino Opta Expansion modules as well as limitation to max two expansion boards. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c950f5e..f5e33f1 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ This library provides an implementation of [OPC/UA](https://en.wikipedia.org/wiki/OPC_Unified_Architecture) by porting the Fraunhofer [`open62541`](https://github.com/open62541/open62541) for the Arduino [Opta](https://www.arduino.cc/pro/hardware-arduino-opta/) `microPLC` family. +Furthermore, the library supports automatic detection, configuration and exposure of up to two Arduino Opta Expansion Boards (i.e. Digital Expansion w/ mechanical relays [`D1608E`](https://store.arduino.cc/products/opta-ext-d1608e), Digital Expansion w/ solid-state relays [`D1608S`](https://store.arduino.cc/products/opta-ext-d1608e), Analog Expansion [`A0602`](https://store.arduino.cc/products/opta-ext-a0602)) via OPC UA. + ### How-to-OPC/UA * Compile and upload [`examples/opcua_server`](examples/opcua_server/opcua_server.ino) ```bash From 7f1877a954d48d3a0d95c24948c07c49170f3842 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 5 Sep 2024 09:35:05 +0200 Subject: [PATCH 29/29] Use polymorphism to obtain the correct SKU number for OPC UA. --- src/expansion/AnalogExpansion.cpp | 9 +++------ src/expansion/AnalogExpansion.h | 10 ++++++++-- src/expansion/DigitalExpansion.h | 2 +- src/expansion/DigitalMechExpansion.h | 17 +++++++++++------ src/expansion/DigitalStSolidExpansion.h | 17 +++++++++++------ src/expansion/Expansion.h | 4 ++++ 6 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/expansion/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp index 65c92b4..febdb08 100644 --- a/src/expansion/AnalogExpansion.cpp +++ b/src/expansion/AnalogExpansion.cpp @@ -28,9 +28,8 @@ AnalogExpansion::AnalogExpansion( UA_Server * server, UA_NodeId const parent_node_id, char * display_name, - char * node_name, - char * model_name) - : Expansion(server, parent_node_id, display_name, node_name, model_name) + char * node_name) + : Expansion(server, parent_node_id, display_name, node_name, (char *)toSKUString().c_str()) , _analog_input_mgr{opcua::AnalogInputManager::create(_server, _node_id)} , _analog_output_mgr{opcua::AnalogOutputManager::create(_server, _node_id)} , _pwm_output_mgr{opcua::PwmOutputManager::create(_server, _node_id)} @@ -62,9 +61,7 @@ AnalogExpansion::create( char node_name[32] = {0}; snprintf(node_name, sizeof(node_name), "AnaExp_%d", exp_num); - char model_name[] = {"AFX00007"}; - - auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name); return instance_ptr; } diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 01ca38a..66fd547 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -50,10 +50,16 @@ class AnalogExpansion : public Expansion UA_Server * server, UA_NodeId const parent_node_id, char * display_name, - char * node_name, - char * model_name); + char * node_name); + virtual ~AnalogExpansion() = default; + virtual std::string + toSKUString() const override final + { + return std::string("AFX00007"); + } + void add_analog_input( UA_Server * server, diff --git a/src/expansion/DigitalExpansion.h b/src/expansion/DigitalExpansion.h index 326bc48..2adbe69 100644 --- a/src/expansion/DigitalExpansion.h +++ b/src/expansion/DigitalExpansion.h @@ -44,7 +44,7 @@ class DigitalExpansion : public Expansion char * display_name, char * node_name, char * model_name); - + virtual ~DigitalExpansion() = default; void add_analog_input( diff --git a/src/expansion/DigitalMechExpansion.h b/src/expansion/DigitalMechExpansion.h index dd3377d..c200ef1 100644 --- a/src/expansion/DigitalMechExpansion.h +++ b/src/expansion/DigitalMechExpansion.h @@ -44,9 +44,7 @@ class DigitalMechExpansion : public DigitalExpansion char node_name[32] = {0}; snprintf(node_name, sizeof(node_name), "DigExpSoli_%d", exp_num); - char model_name[] = {"AFX00005"}; - - auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name); return instance_ptr; } @@ -55,10 +53,17 @@ class DigitalMechExpansion : public DigitalExpansion UA_Server * server, UA_NodeId const parent_node_id, char * display_name, - char * node_name, - char * model_name) - : DigitalExpansion{server, parent_node_id, display_name, node_name, model_name} + char * node_name) + : DigitalExpansion(server, parent_node_id, display_name, node_name, (char *)toSKUString().c_str()) {} + virtual ~DigitalMechExpansion() = default; + + + virtual std::string + toSKUString() const override final + { + return std::string("AFX00005"); + } }; /************************************************************************************** diff --git a/src/expansion/DigitalStSolidExpansion.h b/src/expansion/DigitalStSolidExpansion.h index e386a12..1f50a95 100644 --- a/src/expansion/DigitalStSolidExpansion.h +++ b/src/expansion/DigitalStSolidExpansion.h @@ -44,9 +44,7 @@ class DigitalStSolidExpansion : public DigitalExpansion char node_name[32] = {0}; snprintf(node_name, sizeof(node_name), "DigExpSoli_%d", exp_num); - char model_name[] = {"AFX00006"}; - - auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name); return instance_ptr; } @@ -55,10 +53,17 @@ class DigitalStSolidExpansion : public DigitalExpansion UA_Server * server, UA_NodeId const parent_node_id, char * display_name, - char * node_name, - char * model_name) - : DigitalExpansion{server, parent_node_id, display_name, node_name, model_name} + char * node_name) + : DigitalExpansion{server, parent_node_id, display_name, node_name, (char *)toSKUString().c_str()} {} + virtual ~DigitalStSolidExpansion() = default; + + + virtual std::string + toSKUString() const override final + { + return std::string("AFX00006"); + } }; /************************************************************************************** diff --git a/src/expansion/Expansion.h b/src/expansion/Expansion.h index fdd3cac..edffe50 100644 --- a/src/expansion/Expansion.h +++ b/src/expansion/Expansion.h @@ -40,6 +40,10 @@ class Expansion char * display_name, char * node_name, char * model_name); + virtual ~Expansion() = default; + + virtual std::string + toSKUString() const = 0; protected: