Add OPC-UA simulator

This commit is contained in:
gc87
2021-11-30 10:56:00 +08:00
committed by Parker Liu
parent a13653f5b5
commit 587bf7fefc
2 changed files with 252 additions and 1 deletions
+4 -1
View File
@@ -1,3 +1,6 @@
add_executable(modbus_tcp_server_simulator modbus_tcp_server_sim.c)
target_include_directories(modbus_tcp_server_simulator PRIVATE ${CMAKE_SOURCE_DIR})
target_link_libraries(modbus_tcp_server_simulator neuron-base)
target_link_libraries(modbus_tcp_server_simulator neuron-base)
add_executable(opcua_simulator opcua_simulator.c)
target_link_libraries(opcua_simulator rt open62541 ssl crypto)
+248
View File
@@ -0,0 +1,248 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#include <open62541.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define UNUSED(x) (void) (x)
static volatile UA_Boolean running = true;
static void node_attributes_set(UA_Server *server, char *name, char *node_id,
int type, void *data, const int readonly)
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr.value, data, &UA_TYPES[type]);
attr.description = UA_LOCALIZEDTEXT("en-US", name);
attr.displayName = UA_LOCALIZEDTEXT("en-US", name);
attr.dataType = UA_TYPES[type].typeId;
if (readonly) {
attr.accessLevel = UA_ACCESSLEVELMASK_READ;
} else {
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
}
UA_NodeId integer_node_id = UA_NODEID_STRING(1, node_id);
UA_QualifiedName integer_name = UA_QUALIFIEDNAME(1, name);
UA_NodeId parent_node_id = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_NodeId parent_reference_node_id =
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
UA_Server_addVariableNode(
server, integer_node_id, parent_node_id, parent_reference_node_id,
integer_name, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr,
NULL, NULL);
}
// UA_SByte <-> int8_t
static void data_int8_add(UA_Server *server, char *name, char *node_id,
int8_t data, const int readonly)
{
UA_SByte sbyte = data;
node_attributes_set(server, name, node_id, UA_TYPES_SBYTE, &sbyte,
readonly);
}
// UA_Byte <-> uint8_t
static void data_uint8_add(UA_Server *server, char *name, char *node_id,
uint8_t data, const int readonly)
{
UA_Byte byte = data;
node_attributes_set(server, name, node_id, UA_TYPES_SBYTE, &byte, readonly);
}
// UA_Boolean
static void data_bool_add(UA_Server *server, char *name, char *node_id,
bool data, const int readonly)
{
UA_Boolean boolean = data;
node_attributes_set(server, name, node_id, UA_TYPES_BOOLEAN, &boolean,
readonly);
}
// UA_Int16
static void data_int16_add(UA_Server *server, char *name, char *node_id,
int16_t data, const int readonly)
{
UA_Int16 i16 = data;
node_attributes_set(server, name, node_id, UA_TYPES_INT16, &i16, readonly);
}
// UA_UInt16
static void data_uint16_add(UA_Server *server, char *name, char *node_id,
int16_t data, const int readonly)
{
UA_UInt16 u16 = data;
node_attributes_set(server, name, node_id, UA_TYPES_UINT16, &u16, readonly);
}
// UA_Int32
static void data_int32_add(UA_Server *server, char *name, char *node_id,
int32_t data, const int readonly)
{
UA_Int32 i32 = data;
node_attributes_set(server, name, node_id, UA_TYPES_INT32, &i32, readonly);
}
// UA_UInt32
static void data_uint32_add(UA_Server *server, char *name, char *node_id,
uint32_t data, const int readonly)
{
UA_UInt32 u32 = data;
node_attributes_set(server, name, node_id, UA_TYPES_UINT32, &u32, readonly);
}
// UA_DateTime
// static void data_datetime_add(UA_Server *server, char *name, char *node_id,
// uint32_t data, const int readonly)
// {
// UNUSED(server);
// UNUSED(name);
// UNUSED(node_id);
// UNUSED(data);
// UNUSED(readonly);
// }
// UA_Float
static void data_float_add(UA_Server *server, char *name, char *node_id,
float data, const int readonly)
{
UA_Float f32 = data;
node_attributes_set(server, name, node_id, UA_TYPES_FLOAT, &f32, readonly);
}
// UA_Double
static void data_double_add(UA_Server *server, char *name, char *node_id,
double data, const int readonly)
{
UA_Double f64 = data;
node_attributes_set(server, name, node_id, UA_TYPES_DOUBLE, &f64, readonly);
}
static void data_string_add(UA_Server *server, char *name, char *node_id,
char *data, const int readonly)
{
UA_String str = UA_STRING(data);
node_attributes_set(server, name, node_id, UA_TYPES_STRING, &str, readonly);
}
static UA_StatusCode
current_time_read(UA_Server *server, const UA_NodeId *sessionId,
void *sessionContext, const UA_NodeId *nodeId,
void *nodeContext, UA_Boolean sourceTimeStamp,
const UA_NumericRange *range, UA_DataValue *dataValue)
{
UNUSED(server);
UNUSED(sessionId);
UNUSED(sessionContext);
UNUSED(nodeId);
UNUSED(nodeContext);
UNUSED(sourceTimeStamp);
UNUSED(range);
UA_DateTime now = UA_DateTime_now();
UA_Variant_setScalarCopy(&dataValue->value, &now,
&UA_TYPES[UA_TYPES_DATETIME]);
dataValue->hasValue = true;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
current_time_write(UA_Server *server, const UA_NodeId *sessionId,
void *sessionContext, const UA_NodeId *nodeId,
void *nodeContext, const UA_NumericRange *range,
const UA_DataValue *data)
{
UNUSED(server);
UNUSED(sessionId);
UNUSED(sessionContext);
UNUSED(nodeId);
UNUSED(nodeContext);
UNUSED(range);
UNUSED(data);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Changing the system time is not implemented");
return UA_STATUSCODE_BADINTERNALERROR;
}
static void current_time_datasource_variable_add(UA_Server *server)
{
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("en-US", "type_datetime");
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId currentNodeId = UA_NODEID_STRING(1, "neu.type_datetime");
UA_QualifiedName currentName = UA_QUALIFIEDNAME(1, "type_datetime");
UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
UA_NodeId variableTypeNodeId =
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
UA_DataSource timeDataSource;
timeDataSource.read = current_time_read;
timeDataSource.write = current_time_write;
UA_Server_addDataSourceVariableNode(
server, currentNodeId, parentNodeId, parentReferenceNodeId, currentName,
variableTypeNodeId, attr, timeDataSource, NULL, NULL);
}
int main(int argc, char **argv)
{
UNUSED(argc);
UNUSED(argv);
UA_ServerNetworkLayer nl =
UA_ServerNetworkLayerTCP(UA_ConnectionConfig_default, 4840, 12);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_ServerConfig *config = UA_Server_getConfig(server);
config->networkLayers = &nl;
config->networkLayersSize = 1;
config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;
static UA_UsernamePasswordLogin logins[2] = {
{ UA_STRING_STATIC("user"), UA_STRING_STATIC("123456") },
};
UA_AccessControl_default(
config, false,
&config->securityPolicies[config->securityPoliciesSize - 1].policyUri,
2, logins);
data_int8_add(server, "type_int8", "neu.type.int8", -10, 0);
data_uint8_add(server, "type_uint8", "neu.type.uint8", 10, 0);
data_bool_add(server, "type_bool", "neu.type_bool", true, 0);
data_int16_add(server, "type_int16", "neu.type_int16", -1001, 0);
data_uint16_add(server, "type_uint16", "neu.type_uint16", 1001, 0);
data_int32_add(server, "type_int32", "neu.type_int32", -100, 0);
data_uint32_add(server, "type_uint32", "neu.type_uint32", 111111, 0);
data_float_add(server, "type_float", "neu.type_float", 38.9, 0);
data_double_add(server, "type_double", "neu.type_double", 100038.9999, 0);
data_string_add(server, "type_cstr", "nue.type_cstr", "hello world!", 0);
current_time_datasource_variable_add(server);
UA_StatusCode retval = UA_Server_run(server, &running);
UNUSED(retval);
UA_Server_delete(server);
return 0;
}