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 diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 3016e16..ab92976 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; @@ -175,38 +175,38 @@ 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. */ - 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 +221,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++) { @@ -239,25 +249,143 @@ 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) { auto const exp_analog = opta_expansion_manager_opcua->create_analog_expansion(i); + + 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, + 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", input_num); + exp_analog->add_analog_input( + opc_ua_server, + analog_in_name, + [i, a]() + { + return reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a); + }); + input_num++; + } + + 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, + 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 O%d", output_num); + 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) + { + reinterpret_cast(OptaController.getExpansionPtr(i))->pinVoltage(a, voltage); + }); + 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->add_pwm_output( + opc_ua_server, + pwm_out_name, + [i, p](uint32_t const pwm_period_us, uint32_t const pwm_pulse_width_us) + { + 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++; + } + + /* 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->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); + }); + } } } @@ -269,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), @@ -359,7 +487,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); 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 diff --git a/src/Arduino_open62541.h b/src/Arduino_open62541.h index 9e1aaae..1d0f020 100644 --- a/src/Arduino_open62541.h +++ b/src/Arduino_open62541.h @@ -32,3 +32,9 @@ #if !defined(ARDUINO_OPTA) # 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) diff --git a/src/Opta.cpp b/src/Opta.cpp index be58299..0e7c2aa 100644 --- a/src/Opta.cpp +++ b/src/Opta.cpp @@ -24,24 +24,38 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -Opta::Opta(UA_Server * server, UA_NodeId const & node_id) +Opta::Opta( + UA_Server * server, + 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, "Opta::Ctor: UserButton::create(...) failed."); + 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__); } /************************************************************************************** * 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 +74,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 +94,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 +114,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,61 +134,49 @@ 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; } - 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, "Opta::analog_input_mgr: AnalogInputManager::create(...) failed."); - } - - 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, "Opta::digital_input_mgr: DigitalInputManager::create(...) failed."); - } - - 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, "Opta::relay_mgr: RelayManager::create(...) failed."); - } - - 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, "Opta::led_mgr: LedManager::create(...) failed."); - } - - 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 d3be5cf..21cb80e 100644 --- a/src/Opta.h +++ b/src/Opta.h @@ -42,19 +42,41 @@ class Opta typedef std::shared_ptr SharedPtr; - static SharedPtr create(UA_Server * server, OptaVariant::Type const opta_type); - - - Opta(UA_Server * server, UA_NodeId const & node_id); - - - AnalogInputManager::SharedPtr analog_input_mgr(); - DigitalInputManager::SharedPtr digital_input_mgr(); - RelayManager::SharedPtr relay_mgr(); - LedManager::SharedPtr led_mgr(); - - - [[nodiscard]] UA_NodeId node_id() const { return _node_id; } + static SharedPtr + create( + UA_Server * server, + OptaVariant::Type const opta_type); + + + Opta( + UA_Server * server, + 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); + + 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); private: 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/AnalogExpansion.cpp b/src/expansion/AnalogExpansion.cpp new file mode 100644 index 0000000..febdb08 --- /dev/null +++ b/src/expansion/AnalogExpansion.cpp @@ -0,0 +1,111 @@ +/* + * 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 +{ + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +AnalogExpansion::AnalogExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_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)} + , _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 + **************************************************************************************/ + +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); + + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name); + return instance_ptr; +} + +void +AnalogExpansion::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); +} + +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_read_request, on_write_request_func); +} + +void +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::GetPwmPulseWidthFunc const get_pwm_pulse_width_func) +{ + _pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func); +} + +void +AnalogExpansion::add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state) +{ + _led_mgr->add_led_output(server, display_name, on_set_led_state); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h index 2cacc67..66fd547 100644 --- a/src/expansion/AnalogExpansion.h +++ b/src/expansion/AnalogExpansion.h @@ -17,6 +17,11 @@ #include +#include "../io/led/LedManager.h" +#include "../io/pwm/PwmOutputManager.h" +#include "../io/analog/AnalogInputManager.h" +#include "../io/analog/AnalogOutputManager.h" + /************************************************************************************** * NAMESPACE **************************************************************************************/ @@ -34,28 +39,60 @@ 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) - { - char display_name[64] = {0}; - snprintf(display_name, sizeof(display_name), "Arduino Opta Expansion %d: Analog", exp_num); + static SharedPtr + create( + UA_Server *server, + UA_NodeId const parent_node_id, + uint8_t const exp_num); - char node_name[32] = {0}; - snprintf(node_name, sizeof(node_name), "AnaExp_%d", exp_num); - char model_name[] = {"AFX00007"}; + AnalogExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name); + virtual ~AnalogExpansion() = default; - auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); - return instance_ptr; - } + virtual std::string + toSKUString() const override final + { + return std::string("AFX00007"); + } - 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) - { } + 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::OnReadRequestFunc const on_read_request, + AnalogOutput::OnWriteRequestFunc const on_write_request_func); + + void + add_pwm_output( + UA_Server * server, + const char * display_name, + PwmOutput::SetPwmFunc const set_pwm_func, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func); + + void + add_led_output( + UA_Server * server, + const char * display_name, + Led::OnSetLedStateFunc const on_set_led_state); + + +private: + AnalogInputManager::SharedPtr _analog_input_mgr; + AnalogOutputManager::SharedPtr _analog_output_mgr; + PwmOutputManager::SharedPtr _pwm_output_mgr; + LedManager::SharedPtr _led_mgr; }; /************************************************************************************** diff --git a/src/expansion/DigitalExpansion.cpp b/src/expansion/DigitalExpansion.cpp index 2b72d72..72ee10a 100644 --- a/src/expansion/DigitalExpansion.cpp +++ b/src/expansion/DigitalExpansion.cpp @@ -23,43 +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, "DigitalExpansion::analog_input_mgr: AnalogInputManager::create(...) failed."); - } - - 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, "DigitalExpansion::digital_input_mgr: DigitalInputManager::create(...) failed."); - } +/************************************************************************************** + * 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, "DigitalExpansion::relay_mgr: RelayManager::create(...) failed."); - } + _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 c44f173..2adbe69 100644 --- a/src/expansion/DigitalExpansion.h +++ b/src/expansion/DigitalExpansion.h @@ -38,18 +38,31 @@ 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) - : Expansion(server, parent_node_id, display_name, node_name, model_name) - { } - - - AnalogInputManager::SharedPtr analog_input_mgr(); - DigitalInputManager::SharedPtr digital_input_mgr(); - RelayManager::SharedPtr relay_mgr(); + DigitalExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name); + virtual ~DigitalExpansion() = default; + + 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: diff --git a/src/expansion/DigitalMechExpansion.h b/src/expansion/DigitalMechExpansion.h index 8908487..c200ef1 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); @@ -40,20 +44,26 @@ 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; } - 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} + DigitalMechExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_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 a458fef..1f50a95 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); @@ -40,20 +44,26 @@ 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; } - 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} + DigitalStSolidExpansion( + UA_Server * server, + UA_NodeId const parent_node_id, + char * display_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.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..edffe50 100644 --- a/src/expansion/Expansion.h +++ b/src/expansion/Expansion.h @@ -34,11 +34,16 @@ 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); + virtual ~Expansion() = default; + + virtual std::string + toSKUString() const = 0; protected: 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 new file mode 100644 index 0000000..2df903c --- /dev/null +++ b/src/io/analog/AnalogOutput.cpp @@ -0,0 +1,170 @@ +/* + * 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_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, + 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); + this_ptr->onWriteRequest(server, nodeid, voltage); +} + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +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} +{ + +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +AnalogOutput::SharedPtr +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 = 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); + 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, + "%s: UA_Server_addVariableNode(...) 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, on_read_request, 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, + "%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + UA_ValueCallback callback; + 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)) + { + 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 +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, + UA_NodeId const * node_id, + float const voltage) +{ + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: voltage = %0.2f", __PRETTY_FUNCTION__, 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..0b1332e --- /dev/null +++ b/src/io/analog/AnalogOutput.h @@ -0,0 +1,79 @@ +/* + * 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 OnReadRequestFunc; + typedef std::function OnWriteRequestFunc; + + + static SharedPtr + create( + 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 + onReadRequest( + UA_Server * server, + UA_NodeId const * node_id); + + void + onWriteRequest( + UA_Server * server, + UA_NodeId const * node_id, + float const voltage); + + +private: + UA_NodeId _node_id; + OnReadRequestFunc const _on_read_request; + OnWriteRequestFunc const _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..ea31431 --- /dev/null +++ b/src/io/analog/AnalogOutputManager.cpp @@ -0,0 +1,91 @@ +/* + * 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} +{ + +} + +/************************************************************************************** + * 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, + "%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 +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_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; + } + _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..f025fed --- /dev/null +++ b/src/io/analog/AnalogOutputManager.h @@ -0,0 +1,67 @@ +/* + * 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::OnReadRequestFunc const on_read_request, + AnalogOutput::OnWriteRequestFunc const on_write_request_func); + + +private: + UA_NodeId _node_id; + std::list _analog_output_list; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ 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/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..dfb0126 100644 --- a/src/io/led/Led.h +++ b/src/io/led/Led.h @@ -35,14 +35,25 @@ 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..ad91493 100644 --- a/src/io/led/LedManager.h +++ b/src/io/led/LedManager.h @@ -36,11 +36,20 @@ 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: diff --git a/src/io/pwm/PwmOutput.cpp b/src/io/pwm/PwmOutput.cpp new file mode 100644 index 0000000..7060439 --- /dev/null +++ b/src/io/pwm/PwmOutput.cpp @@ -0,0 +1,301 @@ +/* + * 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_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, + 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_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 +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_us = *(UA_UInt32 *)(data->value.data); + this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_us); +} + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +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, + 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} + , _get_pwm_pulse_width_func{get_pwm_pulse_width_func} + , _pwm_period_us{0} + , _pwm_pulse_width_us{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, + GetPwmPeriodFunc const get_pwm_period_func, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func) +{ + 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 = 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 / us"); + 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 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, "pwm_period_us"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + pwm_out_period_value_attr, + NULL, + &pwm_period_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_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(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc)); + return nullptr; + } + + 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_setNodeContext(pwm_pulse_width_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. */ + _pwm_period_us = _get_pwm_period_func(); + /* Update the variable node. */ + 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__, _pwm_period_us); +} + +void +PwmOutput::onWriteRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * pwm_period_node_id, + 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) +{ + /* Obtain the value of the analog input pin. */ + _pwm_pulse_width_us = _get_pwm_pulse_width_func(); + /* Update the variable node. */ + 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__, _pwm_pulse_width_us); +} + +void +PwmOutput::onWriteRequestPwmPulseWidth( + UA_Server * server, + UA_NodeId const * node_id, + uint32_t const pwm_pulse_width_us) +{ + _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); +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/pwm/PwmOutput.h b/src/io/pwm/PwmOutput.h new file mode 100644 index 0000000..b17b4e4 --- /dev/null +++ b/src/io/pwm/PwmOutput.h @@ -0,0 +1,97 @@ +/* + * 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; + typedef std::function GetPwmPeriodFunc; + typedef std::function GetPwmPulseWidthFunc; + + + static SharedPtr + create( + UA_Server * server, + UA_NodeId const & parent_node_id, + const char * display_name, + SetPwmFunc const set_pwm_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, + GetPwmPulseWidthFunc const get_pwm_pulse_width_func); + + + void + onReadRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * node_id); + + void + onWriteRequestPwmPeriod( + UA_Server * server, + UA_NodeId const * pwm_period_node_id, + 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_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; + GetPwmPulseWidthFunc const _get_pwm_pulse_width_func; + uint32_t _pwm_period_us, _pwm_pulse_width_us; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/io/pwm/PwmOutputManager.cpp b/src/io/pwm/PwmOutputManager.cpp new file mode 100644 index 0000000..0ada80b --- /dev/null +++ b/src/io/pwm/PwmOutputManager.cpp @@ -0,0 +1,94 @@ +/* + * 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, + 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, get_pwm_pulse_width_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..7ff5fd3 --- /dev/null +++ b/src/io/pwm/PwmOutputManager.h @@ -0,0 +1,67 @@ +/* + * 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, + PwmOutput::GetPwmPeriodFunc const get_pwm_period_func, + PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func); + + +private: + UA_NodeId _node_id; + std::list _pwm_output_list; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ 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: