diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index c52346d..668bfaf 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -25,6 +25,11 @@ jobs: with: fqbn: ${{ matrix.board.fqbn }} platforms: ${{ matrix.board.platforms }} + libraries: | + - source-path: ./ + - name: Arduino_Opta_Blueprint + - name: Arduino_SerialUpdater + - name: Arduino_DebugUtils enable-deltas-report: true github-token: ${{ secrets.GITHUB_TOKEN }} sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/examples/opcua_server/opcua_server.ino b/examples/opcua_server/opcua_server.ino index 14d1d8c..c79818e 100644 --- a/examples/opcua_server/opcua_server.ino +++ b/examples/opcua_server/opcua_server.ino @@ -2,14 +2,11 @@ * INCLUDE **************************************************************************************/ -#include "PortentaEthernet.h" -#include "Arduino_open62541.h" +#include +#include +#include /* Arduino_Opta_Blueprint */ #include -#ifndef ARDUINO_OPEN62541_O1HEAP_DEBUG -# define ARDUINO_OPEN62541_O1HEAP_DEBUG (0) /* Change to (1) if you want to see debug messages on Serial concerning o1heap memory calls. */ -#endif - #if MBED_HEAP_STATS_ENABLED && MBED_MEM_TRACING_ENABLED && MBED_STACK_STATS_ENABLED #include "mbed_mem_trace.h" #endif @@ -34,53 +31,6 @@ static int const MODBUS_DEVICE_TEMPERATURE_REGISTER = 0x0001; static int const MODBUS_DEVICE_HUMIDITY_REGISTER = 0x0002; #endif -/************************************************************************************** - * GLUE CODE - **************************************************************************************/ - -extern "C" -{ - int gethostname(char *str, size_t len) { - String ip = Ethernet.localIP().toString(); - memset(str, 0, len); - memcpy(str, ip.c_str(), ip.length()); - return 0; - } - - UA_StatusCode registerFakeInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle, const UA_KeyValueMap *params, UA_InterruptCallback callback, void *interruptContext) { - return UA_STATUSCODE_GOOD; - } - void deregisterFakeInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle) { - return; - } - UA_StatusCode startFakeInterruptManager(UA_EventSource *es) { - return UA_STATUSCODE_GOOD; - } - void stopFakeInterruptManager(UA_EventSource *es) { - return; - } - UA_StatusCode freeFakeInterruptManager(UA_EventSource *es) { - return UA_STATUSCODE_GOOD; - } - - UA_InterruptManager *UA_InterruptManager_new_POSIX(const UA_String eventSourceName) { - static UA_InterruptManager im; - static UA_String name = UA_String_fromChars("fakeES"); - im.eventSource.eventSourceType = UA_EVENTSOURCETYPE_INTERRUPTMANAGER; - UA_String_copy(&eventSourceName, &name); - im.eventSource.start = startFakeInterruptManager; - im.eventSource.stop = stopFakeInterruptManager; - im.eventSource.free = freeFakeInterruptManager; - im.registerInterrupt = registerFakeInterrupt; - im.deregisterInterrupt = deregisterFakeInterrupt; - return &im; - } - - UA_ConnectionManager *UA_ConnectionManager_new_POSIX_UDP(const UA_String eventSourceName) { - return nullptr; - } -} - /************************************************************************************** * GLOBAL VARIABLES **************************************************************************************/ @@ -89,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*1024UL; +static size_t const OPC_UA_SERVER_THREAD_HEAP_SIZE = (256+128)*1024UL; template struct alignas(O1HEAP_ALIGNMENT) OPC_UA_HEAP final : public std::array {}; static OPC_UA_HEAP OPC_UA_SERVER_THREAD_HEAP; @@ -97,9 +47,10 @@ UA_Server * opc_ua_server = nullptr; O1HeapInstance * o1heap_ins = nullptr; rtos::Thread opc_ua_server_thread(osPriorityNormal, OPC_UA_SERVER_THREAD_STACK.size(), OPC_UA_SERVER_THREAD_STACK.data()); -opcua::ArduinoOpta::SharedPtr arduino_opta_opcua; +opcua::Opta::SharedPtr opta_opcua; +opcua::OptaExpansionManager::SharedPtr opta_expansion_manager_opcua; #if USE_MODBUS_SENSOR_MD02 -UA_NodeId modbus_md02_temperature_node_id; +UA_NodeId modbus_md02_temperature_node_id;s #endif /************************************************************************************** @@ -112,69 +63,6 @@ REDIRECT_STDOUT_TO(Serial) * LOCAL FUNCTIONS **************************************************************************************/ -extern "C" void * o1heap_malloc(size_t size) -{ -#if ARDUINO_OPEN62541_O1HEAP_DEBUG - if (!o1heapDoInvariantsHold(o1heap_ins)) - Serial.println("malloc error"); -#endif - - void * new_ptr = o1heapAllocate(o1heap_ins, size); - -#if ARDUINO_OPEN62541_O1HEAP_DEBUG - char msg[64]; - snprintf(msg, sizeof(msg), "malloc: %d (%X)", size, new_ptr); - Serial.println(msg); -#endif - - return new_ptr; -} - -extern "C" void o1heap_free(void * ptr) -{ -#if ARDUINO_OPEN62541_O1HEAP_DEBUG - if (!o1heapDoInvariantsHold(o1heap_ins)) - Serial.println("free error"); - - char msg[64]; - snprintf(msg, sizeof(msg), "free: (%X)", ptr); - Serial.println(msg); -#endif - o1heapFree(o1heap_ins, ptr); -} - -extern "C" void * o1heap_calloc(size_t nelem, size_t elsize) -{ -#if ARDUINO_OPEN62541_O1HEAP_DEBUG - if (!o1heapDoInvariantsHold(o1heap_ins)) - Serial.println("calloc error"); - - char msg[64]; - snprintf(msg, sizeof(msg), "calloc: nelem = %d, elsize = %d", nelem, elsize); - Serial.println(msg); -#endif - - void * ptr = o1heap_malloc(nelem * elsize); - memset(ptr, 0, nelem * elsize); - return ptr; -} - -extern "C" void * o1heap_realloc(void * old_ptr, size_t size) -{ -#if ARDUINO_OPEN62541_O1HEAP_DEBUG - if (!o1heapDoInvariantsHold(o1heap_ins)) - Serial.println("realloc error"); - - char msg[64]; - snprintf(msg, sizeof(msg), "realloc: old_ptr = %X, size = %d", old_ptr, size); - Serial.println(msg); -#endif - void * new_ptr = o1heap_malloc(size); - memcpy(new_ptr, old_ptr, size); - o1heap_free(old_ptr); - return new_ptr; -} - static float arduino_opta_analog_read(pin_size_t const pin) { static float const VOLTAGE_MAX = 3.3; // Maximum voltage that can be read @@ -239,6 +127,10 @@ void setup() set_time(opcua::cvt_time(__DATE__)); /* Configure Arduino Opta with time at compile time as last time of defense. */ } + /* Initialize Opta Expansion module controller. */ + OptaController.begin(); + OptaController.update(); + /* Initialize heap memory. */ o1heap_ins = o1heapInit(OPC_UA_SERVER_THREAD_HEAP.data(), OPC_UA_SERVER_THREAD_HEAP.size()); if (o1heap_ins == nullptr) { @@ -261,12 +153,12 @@ void setup() "Arduino Opta IP: %s", Ethernet.localIP().toString().c_str()); /* Determine the Arduino OPC/UA hardware variant. */ - opcua::ArduinoOptaVariant::Type opta_type; - if (!opcua::ArduinoOptaVariant::get_opta_variant(opta_type)) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "opcua::ArduinoOptaVariant::get_opta_variant(...) failed"); + opcua::OptaVariant::Type opta_type; + if (!opcua::OptaVariant::get_opta_variant(opta_type)) { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "opcua::OptaVariant::get_opta_variant(...) failed"); return; } - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Arduino Opta Variant: %s", opcua::ArduinoOptaVariant::toString(opta_type).c_str()); + UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Arduino Opta Variant: %s", opcua::OptaVariant::toString(opta_type).c_str()); /* Read all analog inputs at least once to have them pre-configured as ADCs. */ std::list const ADC_PIN_LIST = { A0, A1, A2, A3, A4, A5, A6, A7 }; @@ -276,41 +168,97 @@ void setup() analogReadResolution(12); /* Define the Arduino Opta as a OPC/UA object. */ - arduino_opta_opcua = opcua::ArduinoOpta::create(opc_ua_server, opta_type); - if (!arduino_opta_opcua) { - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "opcua::ArduinoOpta::create(...) failed"); + opta_opcua = opcua::Opta::create(opc_ua_server, opta_type); + if (!opta_opcua) { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "opcua::Opta::create(...) failed"); return; } /* Add the various digital input pins. */ - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 1", []() { return arduino_opta_analog_read(A0); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 2", []() { return arduino_opta_analog_read(A1); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 3", []() { return arduino_opta_analog_read(A2); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 4", []() { return arduino_opta_analog_read(A3); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 5", []() { return arduino_opta_analog_read(A4); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 6", []() { return arduino_opta_analog_read(A5); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 7", []() { return arduino_opta_analog_read(A6); }); - arduino_opta_opcua->analog_input_mgr()->add_analog_input(opc_ua_server, "Analog Input 8", []() { return arduino_opta_analog_read(A7); }); + 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); }); /* Add the various digital input pins. */ - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 1", []() { return arduino_opta_digital_read(A0); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 2", []() { return arduino_opta_digital_read(A1); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 3", []() { return arduino_opta_digital_read(A2); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 4", []() { return arduino_opta_digital_read(A3); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 5", []() { return arduino_opta_digital_read(A4); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 6", []() { return arduino_opta_digital_read(A5); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 7", []() { return arduino_opta_digital_read(A6); }); - arduino_opta_opcua->digital_input_mgr()->add_digital_input(opc_ua_server, "Digital Input 8", []() { return arduino_opta_digital_read(A7); }); + 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); }); /* Add the various relay outputs. */ - arduino_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); }); - arduino_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);}); - arduino_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);}); - arduino_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->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);}); /* Add the various LED outputs. */ - if (opta_type == opcua::ArduinoOptaVariant::Type::WiFi) { - arduino_opta_opcua->led_mgr()->add_led_output(opc_ua_server, "User LED", [](bool const value) { pinMode(LEDB, OUTPUT); digitalWrite(LEDB, value); }); + 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); }); + } + + /* Check availability of expansion modules. */ + uint8_t const 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", + i, OptaController.getExpansionType(i), opcua::ExpansionType::toStr(OptaController.getExpansionType(i)).c_str(), OptaController.getExpansionI2Caddress(i)); + + /* Create Arduino Opta Expansion Manager (if necessary). */ + if (opta_expansion_num) { + opta_expansion_manager_opcua = opcua::OptaExpansionManager::create(opc_ua_server); + if (!opta_expansion_manager_opcua) { + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "opcua::OptaExpansionManager::create(...) failed"); + return; + } + } + + /* Expose Arduino Opta expansion module IO via OPC/UA. */ + for(uint8_t i = 0; i < opta_expansion_num; i++) + { + ExpansionType_t const exp_type = OptaController.getExpansionType(i); + + if (exp_type == EXPANSION_OPTA_DIGITAL_MEC || exp_type == EXPANSION_OPTA_DIGITAL_STS) + { + opcua::DigitalExpansion::SharedPtr exp_dig = nullptr; + if (exp_type == EXPANSION_OPTA_DIGITAL_MEC) + exp_dig = opta_expansion_manager_opcua->create_digital_mechanical_expansion(i); + else + exp_dig = opta_expansion_manager_opcua->create_digital_solid_state_expansion(i); + + /* Expose digital/analog pins via OPC/UA. */ + for (uint8_t d = 0; d < OPTA_DIGITAL_IN_NUM; d++) + { + 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); }); + + 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); }); + } + /* 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); }); + } + } + else if (exp_type == EXPANSION_OPTA_ANALOG) + { + auto const exp_analog = opta_expansion_manager_opcua->create_analog_expansion(i); + } } #if USE_MODBUS_SENSOR_MD02 @@ -321,7 +269,7 @@ void setup() UA_NodeId modbus_md02_node_id; rc = UA_Server_addObjectNode(opc_ua_server, UA_NODEID_NULL, - arduino_opta_opcua->node_id(), + opta_opcua->node_id(), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "ModbusRs485Md02"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), @@ -407,6 +355,21 @@ void setup() void loop() { + /* Always call update as fast as possible */ + OptaController.update(); + + /* Determine the number of expansion boards available and call update on them. */ + uint8_t const opta_expansion_num = OptaController.getExpansionNum(); + for(uint8_t i = 0; i < opta_expansion_num; i++) + { + ExpansionType_t const exp_type = OptaController.getExpansionType(i); + if (exp_type == EXPANSION_OPTA_DIGITAL_MEC) + reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); + else if (exp_type == EXPANSION_OPTA_DIGITAL_STS) + reinterpret_cast(OptaController.getExpansionPtr(i))->updateDigitalOutputs(); + } + + /* Toggle main LED signalling progress. */ digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); delay(500); diff --git a/library.properties b/library.properties index 0557f15..dd4148e 100644 --- a/library.properties +++ b/library.properties @@ -10,3 +10,4 @@ url=https://github.com/bcmi-labs/Arduino_open62541 ldflags=-lopen62541 includes=Arduino_open62541.h precompiled=true +depends=Arduino_Opta_Blueprint diff --git a/src/Arduino_open62541.h b/src/Arduino_open62541.h index 68fe6a4..9e1aaae 100644 --- a/src/Arduino_open62541.h +++ b/src/Arduino_open62541.h @@ -14,12 +14,16 @@ **************************************************************************************/ #include "open62541.h" -#include "o1heap/o1heap.h" -#include "NTPUtils.h" -#include "cvt_time.h" -#include "ArduinoOpta.h" -#include "ArduinoOptaVariant.h" +#include "util/o1heap/o1heap.h" +#include "util/o1heap/o1heap_wrapper.h" +#include "util/time/cvt_time.h" +#include "util/time/NTPUtils.h" +#include "util/toStr/ExpansionType.h" + +#include "Opta.h" +#include "OptaVariant.h" +#include "OptaExpansionManager.h" /************************************************************************************** * DEFINES diff --git a/src/ArduinoOpta.cpp b/src/Opta.cpp similarity index 76% rename from src/ArduinoOpta.cpp rename to src/Opta.cpp index 236ca99..be58299 100644 --- a/src/ArduinoOpta.cpp +++ b/src/Opta.cpp @@ -11,7 +11,7 @@ * INCLUDE **************************************************************************************/ -#include "ArduinoOpta.h" +#include "Opta.h" /************************************************************************************** * NAMESPACE @@ -24,7 +24,7 @@ namespace opcua * CTOR/DTOR **************************************************************************************/ -ArduinoOpta::ArduinoOpta(UA_Server * server, UA_NodeId const & node_id) +Opta::Opta(UA_Server * server, UA_NodeId const & node_id) : _server{server} , _node_id{node_id} , _analog_input_mgr{nullptr} @@ -34,25 +34,25 @@ ArduinoOpta::ArduinoOpta(UA_Server * server, UA_NodeId const & node_id) { _usr_button = opcua::UserButton::create(_server, _node_id); if (!_usr_button) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "ArduinoOpta::Ctor: UserButton::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::Ctor: UserButton::create(...) failed."); } /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -ArduinoOpta::SharedPtr ArduinoOpta::create(UA_Server * server, ArduinoOptaVariant::Type const opta_type) +Opta::SharedPtr Opta::create(UA_Server * server, OptaVariant::Type const opta_type) { UA_StatusCode rc = UA_STATUSCODE_GOOD; UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; - oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Arduino Opta"); + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", (char *)OptaVariant::toString(opta_type).c_str()); UA_NodeId node_id; rc = UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), - UA_QUALIFIEDNAME(1, "ArduinoOpta"), + UA_QUALIFIEDNAME(1, "Opta"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, @@ -60,7 +60,7 @@ ArduinoOpta::SharedPtr ArduinoOpta::create(UA_Server * server, ArduinoOptaVarian if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "ArduinoOpta::create: UA_Server_addObjectNode(...) failed with %s", + "Opta::create: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); return nullptr; } @@ -81,13 +81,13 @@ ArduinoOpta::SharedPtr ArduinoOpta::create(UA_Server * server, ArduinoOptaVarian if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "ArduinoOpta::create: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", + "Opta::create: UA_Server_addVariableNode(..., \"ManufacturerName\", ...) failed with %s", UA_StatusCode_name(rc)); return nullptr; } UA_VariableAttributes modelAttr = UA_VariableAttributes_default; - UA_String modelName = UA_STRING((char *)ArduinoOptaVariant::toString(opta_type).c_str()); + UA_String modelName = UA_STRING((char *)OptaVariant::toSKUString(opta_type).c_str()); UA_Variant_setScalar(&modelAttr.value, &modelName, &UA_TYPES[UA_TYPES_STRING]); modelAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ModelName"); rc = UA_Server_addVariableNode(server, @@ -102,7 +102,7 @@ ArduinoOpta::SharedPtr ArduinoOpta::create(UA_Server * server, ArduinoOptaVarian if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "ArduinoOpta::create: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", + "Opta::create: UA_Server_addVariableNode(..., \"ModelName\", ...) failed with %s", UA_StatusCode_name(rc)); return nullptr; } @@ -123,58 +123,58 @@ ArduinoOpta::SharedPtr ArduinoOpta::create(UA_Server * server, ArduinoOptaVarian if (UA_StatusCode_isBad(rc)) { UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "ArduinoOpta::create: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", + "Opta::create: UA_Server_addVariableNode(..., \"Status\", ...) failed with %s", 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); return instance_ptr; } -AnalogInputManager::SharedPtr ArduinoOpta::analog_input_mgr() +AnalogInputManager::SharedPtr Opta::analog_input_mgr() { if (!_analog_input_mgr) { _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); if (!_analog_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "ArduinoOpta::analog_input_mgr: AnalogInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::analog_input_mgr: AnalogInputManager::create(...) failed."); } return _analog_input_mgr; } -DigitalInputManager::SharedPtr ArduinoOpta::digital_input_mgr() +DigitalInputManager::SharedPtr Opta::digital_input_mgr() { if (!_digital_input_mgr) { _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); if (!_digital_input_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "ArduinoOpta::digital_input_mgr: DigitalInputManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::digital_input_mgr: DigitalInputManager::create(...) failed."); } return _digital_input_mgr; } -RelayManager::SharedPtr ArduinoOpta::relay_mgr() +RelayManager::SharedPtr Opta::relay_mgr() { if (!_relay_mgr) { _relay_mgr = opcua::RelayManager::create(_server, _node_id); if (!_relay_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "ArduinoOpta::relay_mgr: RelayManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::relay_mgr: RelayManager::create(...) failed."); } return _relay_mgr; } -LedManager::SharedPtr ArduinoOpta::led_mgr() +LedManager::SharedPtr Opta::led_mgr() { if (!_led_mgr) { _led_mgr = opcua::LedManager::create(_server, _node_id); if (!_led_mgr) - UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "ArduinoOpta::led_mgr: LedManager::create(...) failed."); + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Opta::led_mgr: LedManager::create(...) failed."); } return _led_mgr; diff --git a/src/ArduinoOpta.h b/src/Opta.h similarity index 80% rename from src/ArduinoOpta.h rename to src/Opta.h index 364cd52..d3be5cf 100644 --- a/src/ArduinoOpta.h +++ b/src/Opta.h @@ -17,12 +17,13 @@ #include -#include "LedManager.h" -#include "RelayManager.h" -#include "AnalogInputManager.h" -#include "DigitalInputManager.h" -#include "UserButton.h" -#include "ArduinoOptaVariant.h" +#include "io/led/LedManager.h" +#include "io/button/UserButton.h" +#include "io/relay/RelayManager.h" +#include "io/analog/AnalogInputManager.h" +#include "io/digital/DigitalInputManager.h" + +#include "OptaVariant.h" /************************************************************************************** * NAMESPACE @@ -35,22 +36,27 @@ namespace opcua * CLASS DECLARATION **************************************************************************************/ -class ArduinoOpta +class Opta { public: - typedef std::shared_ptr SharedPtr; + typedef std::shared_ptr SharedPtr; + + + static SharedPtr create(UA_Server * server, OptaVariant::Type const opta_type); - static SharedPtr create(UA_Server * server, ArduinoOptaVariant::Type const opta_type); - ArduinoOpta(UA_Server * server, UA_NodeId const & node_id); + 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; } + private: UA_Server * _server; UA_NodeId _node_id; diff --git a/src/OptaExpansionManager.cpp b/src/OptaExpansionManager.cpp new file mode 100644 index 0000000..95d55cb --- /dev/null +++ b/src/OptaExpansionManager.cpp @@ -0,0 +1,64 @@ +/* + * 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 "OptaExpansionManager.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +DigitalMechExpansion::SharedPtr OptaExpansionManager::create_digital_mechanical_expansion(uint8_t const exp_num) +{ + auto const exp_mech_opcua = opcua::DigitalMechExpansion::create( + _server, + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), + exp_num); + + _dig_mech_exp_list.push_back(exp_mech_opcua); + return exp_mech_opcua; +} + +DigitalStSolidExpansion::SharedPtr OptaExpansionManager::create_digital_solid_state_expansion(uint8_t const exp_num) +{ + auto const exp_solid_state_opcua = opcua::DigitalStSolidExpansion::create( + _server, + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), + exp_num); + + _dig_solid_state_exp_list.push_back(exp_solid_state_opcua); + return exp_solid_state_opcua; +} + +AnalogExpansion::SharedPtr OptaExpansionManager::create_analog_expansion(uint8_t const exp_num) +{ + auto const exp_analog_opcua = opcua::AnalogExpansion::create( + _server, + UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), + exp_num); + + _analog_exp_list.push_back(exp_analog_opcua); + return exp_analog_opcua; +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/OptaExpansionManager.h b/src/OptaExpansionManager.h new file mode 100644 index 0000000..c3fef8d --- /dev/null +++ b/src/OptaExpansionManager.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 "expansion/AnalogExpansion.h" +#include "expansion/DigitalMechExpansion.h" +#include "expansion/DigitalStSolidExpansion.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class OptaExpansionManager +{ +public: + typedef std::shared_ptr SharedPtr; + + + static SharedPtr create(UA_Server * server) { + return std::make_shared(server); + } + + + OptaExpansionManager(UA_Server * server) + : _server{server} + { } + + + DigitalMechExpansion::SharedPtr create_digital_mechanical_expansion(uint8_t const exp_num); + DigitalStSolidExpansion::SharedPtr create_digital_solid_state_expansion(uint8_t const exp_num); + AnalogExpansion::SharedPtr create_analog_expansion(uint8_t const exp_num); + +private: + UA_Server * _server; + + std::list _dig_mech_exp_list; + std::list _dig_solid_state_exp_list; + std::list _analog_exp_list; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/ArduinoOptaVariant.cpp b/src/OptaVariant.cpp similarity index 66% rename from src/ArduinoOptaVariant.cpp rename to src/OptaVariant.cpp index fb1b503..4c8e751 100644 --- a/src/ArduinoOptaVariant.cpp +++ b/src/OptaVariant.cpp @@ -11,7 +11,7 @@ * INCLUDE **************************************************************************************/ -#include "ArduinoOptaVariant.h" +#include "OptaVariant.h" #if __has_include("opta_info.h") # include @@ -32,18 +32,18 @@ namespace opcua * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -bool ArduinoOptaVariant::get_opta_variant(Type & type) +bool OptaVariant::get_opta_variant(Type & type) { OptaBoardInfo * info = boardInfo(); if (info->_board_functionalities.ethernet && info->_board_functionalities.wifi && info->_board_functionalities.rs485) { - type = ArduinoOptaVariant::Type::WiFi; + type = OptaVariant::Type::WiFi; } else if (info->_board_functionalities.ethernet && info->_board_functionalities.rs485) { - type = ArduinoOptaVariant::Type::RS485; + type = OptaVariant::Type::RS485; } else if (info->_board_functionalities.ethernet) { - type = ArduinoOptaVariant::Type::Lite; + type = OptaVariant::Type::Lite; } else return false; @@ -51,13 +51,24 @@ bool ArduinoOptaVariant::get_opta_variant(Type & type) return true; } -std::string ArduinoOptaVariant::toString(Type const type) +std::string OptaVariant::toString(Type const type) { switch(type) { - case ArduinoOptaVariant::Type::WiFi: return std::string("Arduino Opta WiFi"); break; - case ArduinoOptaVariant::Type::RS485: return std::string("Arduino Opta RS485"); break; - case ArduinoOptaVariant::Type::Lite: return std::string("Arduino Opta Lite"); break; + case OptaVariant::Type::WiFi: return std::string("Arduino Opta WiFi"); break; + case OptaVariant::Type::RS485: return std::string("Arduino Opta RS485"); break; + case OptaVariant::Type::Lite: return std::string("Arduino Opta Lite"); break; + default: __builtin_unreachable(); break; + } +} + +std::string OptaVariant::toSKUString(Type const type) +{ + switch(type) + { + 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; default: __builtin_unreachable(); break; } } diff --git a/src/ArduinoOptaVariant.h b/src/OptaVariant.h similarity index 90% rename from src/ArduinoOptaVariant.h rename to src/OptaVariant.h index e5d87c8..719da3c 100644 --- a/src/ArduinoOptaVariant.h +++ b/src/OptaVariant.h @@ -26,17 +26,18 @@ namespace opcua * CLASS DECLARATION **************************************************************************************/ -class ArduinoOptaVariant +class OptaVariant { public: - ArduinoOptaVariant() = delete; - ArduinoOptaVariant(ArduinoOptaVariant const &) = delete; + 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); }; /************************************************************************************** diff --git a/src/expansion/AnalogExpansion.h b/src/expansion/AnalogExpansion.h new file mode 100644 index 0000000..2cacc67 --- /dev/null +++ b/src/expansion/AnalogExpansion.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "Expansion.h" + +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class AnalogExpansion : public Expansion +{ +public: + 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); + + char node_name[32] = {0}; + snprintf(node_name, sizeof(node_name), "AnaExp_%d", exp_num); + + char model_name[] = {"AFX00007"}; + + auto const instance_ptr = std::make_shared(server, parent_node_id, display_name, node_name, model_name); + return instance_ptr; + } + + + 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) + { } +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/DigitalExpansion.cpp b/src/expansion/DigitalExpansion.cpp new file mode 100644 index 0000000..2b72d72 --- /dev/null +++ b/src/expansion/DigitalExpansion.cpp @@ -0,0 +1,69 @@ +/* + * 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 "DigitalExpansion.h" + +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +AnalogInputManager::SharedPtr DigitalExpansion::analog_input_mgr() +{ + if (!_analog_input_mgr) + { + _analog_input_mgr = opcua::AnalogInputManager::create(_server, _node_id); + if (!_analog_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::analog_input_mgr: AnalogInputManager::create(...) failed."); + } + + return _analog_input_mgr; +} + +DigitalInputManager::SharedPtr DigitalExpansion::digital_input_mgr() +{ + if (!_digital_input_mgr) + { + _digital_input_mgr = opcua::DigitalInputManager::create(_server, _node_id); + if (!_digital_input_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::digital_input_mgr: DigitalInputManager::create(...) failed."); + } + + return _digital_input_mgr; +} + +RelayManager::SharedPtr DigitalExpansion::relay_mgr() +{ + if (!_relay_mgr) + { + _relay_mgr = opcua::RelayManager::create(_server, _node_id); + if (!_relay_mgr) + UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "DigitalExpansion::relay_mgr: RelayManager::create(...) failed."); + } + + return _relay_mgr; +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/DigitalExpansion.h b/src/expansion/DigitalExpansion.h new file mode 100644 index 0000000..c44f173 --- /dev/null +++ b/src/expansion/DigitalExpansion.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Arduino + * + * SPDX-License-Identifier: MPL-2.0 + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "Expansion.h" + +#include + +#include "../io/relay/RelayManager.h" +#include "../io/analog/AnalogInputManager.h" +#include "../io/digital/DigitalInputManager.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class DigitalExpansion : public Expansion +{ +public: + 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(); + + +private: + AnalogInputManager::SharedPtr _analog_input_mgr; + DigitalInputManager::SharedPtr _digital_input_mgr; + RelayManager::SharedPtr _relay_mgr; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/DigitalMechExpansion.h b/src/expansion/DigitalMechExpansion.h new file mode 100644 index 0000000..8908487 --- /dev/null +++ b/src/expansion/DigitalMechExpansion.h @@ -0,0 +1,63 @@ +/* + * 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 "DigitalExpansion.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class DigitalMechExpansion : public DigitalExpansion +{ +public: + 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: Digital (Mechanical)", exp_num); + + 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); + 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} + {} +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/DigitalStSolidExpansion.h b/src/expansion/DigitalStSolidExpansion.h new file mode 100644 index 0000000..a458fef --- /dev/null +++ b/src/expansion/DigitalStSolidExpansion.h @@ -0,0 +1,63 @@ +/* + * 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 "DigitalExpansion.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class DigitalStSolidExpansion : public DigitalExpansion +{ +public: + 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: Digital (Solid State)", exp_num); + + 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); + 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} + {} +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/Expansion.cpp b/src/expansion/Expansion.cpp new file mode 100644 index 0000000..0e4bd36 --- /dev/null +++ b/src/expansion/Expansion.cpp @@ -0,0 +1,123 @@ +/* + * 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 "Expansion.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +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) + : _server{server} +{ + UA_StatusCode rc = UA_STATUSCODE_GOOD; + + UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; + oAttr.displayName = UA_LOCALIZEDTEXT("en-US", display_name); + rc = UA_Server_addObjectNode(server, + UA_NODEID_NULL, + parent_node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_QUALIFIEDNAME(1, node_name), + 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, + "Expansion::Ctor: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc)); + return; + } + + UA_VariableAttributes mnAttr = UA_VariableAttributes_default; + UA_String manufacturerName = UA_STRING("Arduino"); + UA_Variant_setScalar(&mnAttr.value, &manufacturerName, &UA_TYPES[UA_TYPES_STRING]); + mnAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ManufacturerName"); + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + _node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "ManufacturerName"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + mnAttr, + NULL, + NULL); + 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)); + return; + } + + UA_VariableAttributes modelAttr = UA_VariableAttributes_default; + UA_String modelName = UA_STRING(model_name); + UA_Variant_setScalar(&modelAttr.value, &modelName, &UA_TYPES[UA_TYPES_STRING]); + modelAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ModelName"); + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + _node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "ModelName"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + modelAttr, + NULL, + NULL); + 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)); + return; + } + + UA_VariableAttributes statusAttr = UA_VariableAttributes_default; + UA_Boolean status = true; + UA_Variant_setScalar(&statusAttr.value, &status, &UA_TYPES[UA_TYPES_BOOLEAN]); + statusAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Status"); + rc = UA_Server_addVariableNode(server, + UA_NODEID_NULL, + _node_id, + UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), + UA_QUALIFIEDNAME(1, "Status"), + UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), + statusAttr, + NULL, + NULL); + 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)); + return; + } +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/expansion/Expansion.h b/src/expansion/Expansion.h new file mode 100644 index 0000000..9ead3ca --- /dev/null +++ b/src/expansion/Expansion.h @@ -0,0 +1,53 @@ +/* + * 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 + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class Expansion +{ +public: + typedef std::shared_ptr SharedPtr; + + + Expansion(UA_Server * server, + UA_NodeId const parent_node_id, + char * display_name, + char * node_name, + char * model_name); + + +protected: + UA_Server * _server; + UA_NodeId _node_id; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* opcua */ diff --git a/src/AnalogInput.cpp b/src/io/analog/AnalogInput.cpp similarity index 100% rename from src/AnalogInput.cpp rename to src/io/analog/AnalogInput.cpp diff --git a/src/AnalogInput.h b/src/io/analog/AnalogInput.h similarity index 98% rename from src/AnalogInput.h rename to src/io/analog/AnalogInput.h index d759888..2585702 100644 --- a/src/AnalogInput.h +++ b/src/io/analog/AnalogInput.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/AnalogInputManager.cpp b/src/io/analog/AnalogInputManager.cpp similarity index 100% rename from src/AnalogInputManager.cpp rename to src/io/analog/AnalogInputManager.cpp diff --git a/src/AnalogInputManager.h b/src/io/analog/AnalogInputManager.h similarity index 98% rename from src/AnalogInputManager.h rename to src/io/analog/AnalogInputManager.h index 4d1061f..e063dc3 100644 --- a/src/AnalogInputManager.h +++ b/src/io/analog/AnalogInputManager.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/UserButton.cpp b/src/io/button/UserButton.cpp similarity index 100% rename from src/UserButton.cpp rename to src/io/button/UserButton.cpp diff --git a/src/UserButton.h b/src/io/button/UserButton.h similarity index 98% rename from src/UserButton.h rename to src/io/button/UserButton.h index 7eedb70..c0173b4 100644 --- a/src/UserButton.h +++ b/src/io/button/UserButton.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include diff --git a/src/DigitalInput.cpp b/src/io/digital/DigitalInput.cpp similarity index 100% rename from src/DigitalInput.cpp rename to src/io/digital/DigitalInput.cpp diff --git a/src/DigitalInput.h b/src/io/digital/DigitalInput.h similarity index 98% rename from src/DigitalInput.h rename to src/io/digital/DigitalInput.h index 3d13dde..2b52d14 100644 --- a/src/DigitalInput.h +++ b/src/io/digital/DigitalInput.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/DigitalInputManager.cpp b/src/io/digital/DigitalInputManager.cpp similarity index 100% rename from src/DigitalInputManager.cpp rename to src/io/digital/DigitalInputManager.cpp diff --git a/src/DigitalInputManager.h b/src/io/digital/DigitalInputManager.h similarity index 98% rename from src/DigitalInputManager.h rename to src/io/digital/DigitalInputManager.h index 97c4736..a128d08 100644 --- a/src/DigitalInputManager.h +++ b/src/io/digital/DigitalInputManager.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/Led.cpp b/src/io/led/Led.cpp similarity index 100% rename from src/Led.cpp rename to src/io/led/Led.cpp diff --git a/src/Led.h b/src/io/led/Led.h similarity index 98% rename from src/Led.h rename to src/io/led/Led.h index f0b4185..86c87d8 100644 --- a/src/Led.h +++ b/src/io/led/Led.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/LedManager.cpp b/src/io/led/LedManager.cpp similarity index 99% rename from src/LedManager.cpp rename to src/io/led/LedManager.cpp index 75e336f..e9a5009 100644 --- a/src/LedManager.cpp +++ b/src/io/led/LedManager.cpp @@ -13,8 +13,6 @@ #include "LedManager.h" -#include - /************************************************************************************** * NAMESPACE **************************************************************************************/ diff --git a/src/LedManager.h b/src/io/led/LedManager.h similarity index 98% rename from src/LedManager.h rename to src/io/led/LedManager.h index 50b073b..3be94c3 100644 --- a/src/LedManager.h +++ b/src/io/led/LedManager.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/Relay.cpp b/src/io/relay/Relay.cpp similarity index 100% rename from src/Relay.cpp rename to src/io/relay/Relay.cpp diff --git a/src/Relay.h b/src/io/relay/Relay.h similarity index 98% rename from src/Relay.h rename to src/io/relay/Relay.h index 2e27176..837a870 100644 --- a/src/Relay.h +++ b/src/io/relay/Relay.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/RelayManager.cpp b/src/io/relay/RelayManager.cpp similarity index 99% rename from src/RelayManager.cpp rename to src/io/relay/RelayManager.cpp index 1dd070e..a1d1d95 100644 --- a/src/RelayManager.cpp +++ b/src/io/relay/RelayManager.cpp @@ -13,8 +13,6 @@ #include "RelayManager.h" -#include - /************************************************************************************** * NAMESPACE **************************************************************************************/ diff --git a/src/RelayManager.h b/src/io/relay/RelayManager.h similarity index 98% rename from src/RelayManager.h rename to src/io/relay/RelayManager.h index f8851bd..e54e557 100644 --- a/src/RelayManager.h +++ b/src/io/relay/RelayManager.h @@ -13,7 +13,7 @@ * INCLUDE **************************************************************************************/ -#include "open62541.h" +#include "../../open62541.h" #include #include diff --git a/src/arch/common/ua_timer.c b/src/open62541/arch/common/ua_timer.c similarity index 100% rename from src/arch/common/ua_timer.c rename to src/open62541/arch/common/ua_timer.c diff --git a/src/arch/common/ua_timer.h b/src/open62541/arch/common/ua_timer.h similarity index 99% rename from src/arch/common/ua_timer.h rename to src/open62541/arch/common/ua_timer.h index 2ef6b49..f8af1d1 100644 --- a/src/arch/common/ua_timer.h +++ b/src/open62541/arch/common/ua_timer.h @@ -9,7 +9,7 @@ #ifndef UA_TIMER_H_ #define UA_TIMER_H_ -#include "../../open62541.h" +#include "../../../open62541.h" #include "../../deps/ziptree.h" diff --git a/src/arch/eventloop_common.c b/src/open62541/arch/eventloop_common.c similarity index 100% rename from src/arch/eventloop_common.c rename to src/open62541/arch/eventloop_common.c diff --git a/src/arch/eventloop_common.h b/src/open62541/arch/eventloop_common.h similarity index 97% rename from src/arch/eventloop_common.h rename to src/open62541/arch/eventloop_common.h index a55d284..a0c161c 100644 --- a/src/arch/eventloop_common.h +++ b/src/open62541/arch/eventloop_common.h @@ -9,7 +9,7 @@ #ifndef UA_EVENTLOOP_COMMON_H_ #define UA_EVENTLOOP_COMMON_H_ -#include "../open62541.h" +#include "../../open62541.h" /* Utility definitions to be used in EventLoop implementations. * Not part of the public API. */ diff --git a/src/arch/eventloop_posix.cpp b/src/open62541/arch/eventloop_posix.cpp similarity index 100% rename from src/arch/eventloop_posix.cpp rename to src/open62541/arch/eventloop_posix.cpp diff --git a/src/arch/eventloop_posix.h b/src/open62541/arch/eventloop_posix.h similarity index 99% rename from src/arch/eventloop_posix.h rename to src/open62541/arch/eventloop_posix.h index bbb8ea7..4021fb0 100644 --- a/src/arch/eventloop_posix.h +++ b/src/open62541/arch/eventloop_posix.h @@ -9,7 +9,7 @@ #ifndef UA_EVENTLOOP_POSIX_H_ #define UA_EVENTLOOP_POSIX_H_ -#include "../open62541.h" +#include "../../open62541.h" #if defined(UA_ARCHITECTURE_POSIX) || defined(UA_ARCHITECTURE_WIN32) diff --git a/src/arch/eventloop_posix_tcp.cpp b/src/open62541/arch/eventloop_posix_tcp.cpp similarity index 99% rename from src/arch/eventloop_posix_tcp.cpp rename to src/open62541/arch/eventloop_posix_tcp.cpp index 2834d1a..46fa576 100644 --- a/src/arch/eventloop_posix_tcp.cpp +++ b/src/open62541/arch/eventloop_posix_tcp.cpp @@ -6,7 +6,7 @@ * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) */ -#include "../open62541.h" +#include "../../open62541.h" #include "eventloop_posix.h" #include "eventloop_common.h" diff --git a/src/arch/posix/eventloop_mbed.cpp b/src/open62541/arch/posix/eventloop_mbed.cpp similarity index 99% rename from src/arch/posix/eventloop_mbed.cpp rename to src/open62541/arch/posix/eventloop_mbed.cpp index 4e5e57e..b8c01de 100644 --- a/src/arch/posix/eventloop_mbed.cpp +++ b/src/open62541/arch/posix/eventloop_mbed.cpp @@ -85,7 +85,7 @@ UA_EventLoopPOSIX_deregisterFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { } rtos::EventFlags _events; -#include "../../o1heap/o1heap.h" +#include "../../../util/o1heap/o1heap.h" UA_StatusCode UA_EventLoopPOSIX_pollFDs(UA_EventLoopPOSIX *el, UA_DateTime listenTimeout) { diff --git a/src/arch/posix/mbed_tcp.cpp b/src/open62541/arch/posix/mbed_tcp.cpp similarity index 100% rename from src/arch/posix/mbed_tcp.cpp rename to src/open62541/arch/posix/mbed_tcp.cpp diff --git a/src/arch/posix/mbed_tcp.h b/src/open62541/arch/posix/mbed_tcp.h similarity index 100% rename from src/arch/posix/mbed_tcp.h rename to src/open62541/arch/posix/mbed_tcp.h diff --git a/src/arch/posix/ua_architecture.h b/src/open62541/arch/posix/ua_architecture.h similarity index 98% rename from src/arch/posix/ua_architecture.h rename to src/open62541/arch/posix/ua_architecture.h index adab2f9..f8f15da 100644 --- a/src/arch/posix/ua_architecture.h +++ b/src/open62541/arch/posix/ua_architecture.h @@ -8,7 +8,7 @@ #ifndef PLUGINS_ARCH_POSIX_UA_ARCHITECTURE_H_ #define PLUGINS_ARCH_POSIX_UA_ARCHITECTURE_H_ -#include "../../open62541.h" +#include "../../../open62541.h" #ifdef UA_ARCHITECTURE_POSIX diff --git a/src/arch/posix/ua_clock.cpp b/src/open62541/arch/posix/ua_clock.cpp similarity index 97% rename from src/arch/posix/ua_clock.cpp rename to src/open62541/arch/posix/ua_clock.cpp index 5bdbbfb..1d1bb2c 100644 --- a/src/arch/posix/ua_clock.cpp +++ b/src/open62541/arch/posix/ua_clock.cpp @@ -6,7 +6,7 @@ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA */ -#include "../../open62541.h" +#include "../../../open62541.h" #include diff --git a/src/deps/mp_printf.h b/src/open62541/deps/mp_printf.h similarity index 100% rename from src/deps/mp_printf.h rename to src/open62541/deps/mp_printf.h diff --git a/src/deps/open62541_queue.h b/src/open62541/deps/open62541_queue.h similarity index 100% rename from src/deps/open62541_queue.h rename to src/open62541/deps/open62541_queue.h diff --git a/src/deps/ziptree.h b/src/open62541/deps/ziptree.h similarity index 100% rename from src/deps/ziptree.h rename to src/open62541/deps/ziptree.h diff --git a/src/open62541/glue.cpp b/src/open62541/glue.cpp new file mode 100644 index 0000000..6a026df --- /dev/null +++ b/src/open62541/glue.cpp @@ -0,0 +1,76 @@ +/* + * 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 +#include "../open62541.h" + +/************************************************************************************** + * GLUE CODE + **************************************************************************************/ + +extern "C" +{ + + int gethostname(char *str, size_t len) + { + String ip = Ethernet.localIP().toString(); + memset(str, 0, len); + memcpy(str, ip.c_str(), ip.length()); + return 0; + } + + UA_StatusCode registerFakeInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle, const UA_KeyValueMap *params, UA_InterruptCallback callback, void *interruptContext) + { + return UA_STATUSCODE_GOOD; + } + + void deregisterFakeInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle) + { + return; + } + + UA_StatusCode startFakeInterruptManager(UA_EventSource *es) + { + return UA_STATUSCODE_GOOD; + } + + void stopFakeInterruptManager(UA_EventSource *es) + { + return; + } + + UA_StatusCode freeFakeInterruptManager(UA_EventSource *es) + { + return UA_STATUSCODE_GOOD; + } + + UA_InterruptManager *UA_InterruptManager_new_POSIX(const UA_String eventSourceName) + { + static UA_InterruptManager im; + static UA_String name = UA_String_fromChars("fakeES"); + im.eventSource.eventSourceType = UA_EVENTSOURCETYPE_INTERRUPTMANAGER; + UA_String_copy(&eventSourceName, &name); + im.eventSource.start = startFakeInterruptManager; + im.eventSource.stop = stopFakeInterruptManager; + im.eventSource.free = freeFakeInterruptManager; + im.registerInterrupt = registerFakeInterrupt; + im.deregisterInterrupt = deregisterFakeInterrupt; + return &im; + } + + UA_ConnectionManager *UA_ConnectionManager_new_POSIX_UDP(const UA_String eventSourceName) + { + return nullptr; + } + +} /* extern "C" */ diff --git a/src/o1heap/o1heap.c b/src/util/o1heap/o1heap.c similarity index 100% rename from src/o1heap/o1heap.c rename to src/util/o1heap/o1heap.c diff --git a/src/o1heap/o1heap.h b/src/util/o1heap/o1heap.h similarity index 100% rename from src/o1heap/o1heap.h rename to src/util/o1heap/o1heap.h diff --git a/src/util/o1heap/o1heap_wrapper.cpp b/src/util/o1heap/o1heap_wrapper.cpp new file mode 100644 index 0000000..6a1a790 --- /dev/null +++ b/src/util/o1heap/o1heap_wrapper.cpp @@ -0,0 +1,99 @@ +/* + * 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 "o1heap_wrapper.h" + +#include "o1heap.h" + +#include + +/************************************************************************************** + * DEFINES + **************************************************************************************/ + +#ifndef ARDUINO_OPEN62541_O1HEAP_DEBUG +# define ARDUINO_OPEN62541_O1HEAP_DEBUG (0) /* Change to (1) if you want to see debug messages on Serial concerning o1heap memory calls. */ +#endif + +/************************************************************************************** + * EXTERN DECLARATION + **************************************************************************************/ + +extern O1HeapInstance * o1heap_ins; /* Access o1heap_ins declared in the sketch. */ + +/************************************************************************************** + * FUNCTION DEFINTIION + **************************************************************************************/ + +extern "C" void * o1heap_malloc(size_t size) +{ +#if ARDUINO_OPEN62541_O1HEAP_DEBUG + if (!o1heapDoInvariantsHold(o1heap_ins)) + Serial.println("malloc error"); +#endif + + void * new_ptr = o1heapAllocate(o1heap_ins, size); + +#if ARDUINO_OPEN62541_O1HEAP_DEBUG + char msg[64]; + snprintf(msg, sizeof(msg), "malloc: %d (%X)", size, new_ptr); + Serial.println(msg); +#endif + + return new_ptr; +} + +extern "C" void o1heap_free(void * ptr) +{ +#if ARDUINO_OPEN62541_O1HEAP_DEBUG + if (!o1heapDoInvariantsHold(o1heap_ins)) + Serial.println("free error"); + + char msg[64]; + snprintf(msg, sizeof(msg), "free: (%X)", ptr); + Serial.println(msg); +#endif + o1heapFree(o1heap_ins, ptr); +} + +extern "C" void * o1heap_calloc(size_t nelem, size_t elsize) +{ +#if ARDUINO_OPEN62541_O1HEAP_DEBUG + if (!o1heapDoInvariantsHold(o1heap_ins)) + Serial.println("calloc error"); + + char msg[64]; + snprintf(msg, sizeof(msg), "calloc: nelem = %d, elsize = %d", nelem, elsize); + Serial.println(msg); +#endif + + void * ptr = o1heap_malloc(nelem * elsize); + memset(ptr, 0, nelem * elsize); + return ptr; +} + +extern "C" void * o1heap_realloc(void * old_ptr, size_t size) +{ +#if ARDUINO_OPEN62541_O1HEAP_DEBUG + if (!o1heapDoInvariantsHold(o1heap_ins)) + Serial.println("realloc error"); + + char msg[64]; + snprintf(msg, sizeof(msg), "realloc: old_ptr = %X, size = %d", old_ptr, size); + Serial.println(msg); +#endif + void * new_ptr = o1heap_malloc(size); + memcpy(new_ptr, old_ptr, size); + o1heap_free(old_ptr); + return new_ptr; +} diff --git a/src/util/o1heap/o1heap_wrapper.h b/src/util/o1heap/o1heap_wrapper.h new file mode 100644 index 0000000..0c163da --- /dev/null +++ b/src/util/o1heap/o1heap_wrapper.h @@ -0,0 +1,33 @@ +/* + * 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 + +/************************************************************************************** + * FUNCTION DECLARATION + **************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +void * o1heap_malloc(size_t size); +void o1heap_free(void * ptr); +void * o1heap_calloc(size_t nelem, size_t elsize); +void * o1heap_realloc(void * old_ptr, size_t size); + +#ifdef __cplusplus +} +#endif diff --git a/src/NTPUtils.cpp b/src/util/time/NTPUtils.cpp similarity index 99% rename from src/NTPUtils.cpp rename to src/util/time/NTPUtils.cpp index 5aac874..b70a485 100644 --- a/src/NTPUtils.cpp +++ b/src/util/time/NTPUtils.cpp @@ -13,7 +13,6 @@ #include "NTPUtils.h" - /************************************************************************************** * NAMESPACE **************************************************************************************/ diff --git a/src/NTPUtils.h b/src/util/time/NTPUtils.h similarity index 100% rename from src/NTPUtils.h rename to src/util/time/NTPUtils.h diff --git a/src/cvt_time.cpp b/src/util/time/cvt_time.cpp similarity index 100% rename from src/cvt_time.cpp rename to src/util/time/cvt_time.cpp diff --git a/src/cvt_time.h b/src/util/time/cvt_time.h similarity index 100% rename from src/cvt_time.h rename to src/util/time/cvt_time.h diff --git a/src/util/toStr/ExpansionType.h b/src/util/toStr/ExpansionType.h new file mode 100644 index 0000000..2bf5910 --- /dev/null +++ b/src/util/toStr/ExpansionType.h @@ -0,0 +1,58 @@ +/* + * 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 + +#include "OptaBlue.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace opcua +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class ExpansionType +{ +public: + ExpansionType() = delete; + ExpansionType(ExpansionType const &) = delete; + + static std::string toStr(ExpansionType_t const type) + { + if(type == EXPANSION_NOT_VALID) + return std::string("Invalid"); + else if(type == EXPANSION_OPTA_DIGITAL_MEC) + return std::string("Digital [Mech.]"); + else if(type == EXPANSION_OPTA_DIGITAL_STS) + return std::string("Digital [Solid]"); + else if(type == EXPANSION_DIGITAL_INVALID) + return std::string("Digital [Inva.]"); + else if(type == EXPANSION_OPTA_ANALOG) + return std::string("Analog"); + else + return std::string("Unknown"); + } +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +}