--- /dev/null
+#include <open62541/plugin/log_stdout.h>
+#include <open62541/server.h>
+#include <open62541/server_config_default.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <wdf.h>
+
+typedef struct {
+ UA_Server *server;
+ UA_Int16 ns;
+ UA_NodeId renishawNode;
+} App;
+
+static volatile UA_Boolean is_running = true;
+
+static void on_interrupt(int signo)
+{
+ UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
+ is_running = false;
+}
+
+static int usage(int exitCode)
+{
+ fprintf(stderr, "usage: opc_server ?-port NUM? FILENAME\n");
+ exit(exitCode);
+}
+
+static UA_StatusCode add_float(App *app, const char *name, const char *displayName, UA_Float value)
+{
+ UA_VariableAttributes attr = UA_VariableAttributes_default;
+ if (displayName != NULL)
+ attr.displayName = UA_LOCALIZEDTEXT_ALLOC("en-US", displayName);
+ UA_Variant_setScalar(&attr.value, &value, &UA_TYPES[UA_TYPES_FLOAT]);
+
+ char id[64] = {0};
+ strcat(id, "renishaw.spd.");
+ strcat(id, name);
+
+ UA_NodeId nodeId = UA_NODEID_STRING(app->ns, id);
+ UA_NodeId parentId = app->renishawNode;
+ UA_NodeId parentRefId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
+ UA_NodeId varType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
+ UA_QualifiedName browseName = UA_QUALIFIEDNAME_ALLOC(app->ns, name);
+
+ return UA_Server_addVariableNode(
+ app->server, nodeId, parentId, parentRefId, browseName,
+ varType, attr, NULL, NULL);
+}
+
+static UA_StatusCode add_int32(App *app, const char *name, const char *displayName, UA_Int32 value)
+{
+ UA_VariableAttributes attr = UA_VariableAttributes_default;
+ if (displayName != NULL)
+ attr.displayName = UA_LOCALIZEDTEXT_ALLOC("en-US", displayName);
+ UA_Variant_setScalar(&attr.value, &value, &UA_TYPES[UA_TYPES_INT32]);
+
+ char id[64] = {0};
+ strcat(id, "renishaw.spd.");
+ strcat(id, name);
+
+ UA_NodeId nodeId = UA_NODEID_STRING_ALLOC(app->ns, id);
+ UA_NodeId parentId = app->renishawNode;
+ UA_NodeId parentRefId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
+ UA_NodeId varType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
+ UA_QualifiedName browseName = UA_QUALIFIEDNAME_ALLOC(app->ns, name);
+
+ return UA_Server_addVariableNode(
+ app->server, nodeId, parentId, parentRefId, browseName,
+ varType, attr, NULL, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned short port = 4840;
+ const char *filename = argv[argc - 1];
+
+ if (argc == 4 && strcmp("-port", argv[1]) == 0)
+ port = (unsigned short)strtoul(argv[2], NULL, 0);
+ else if (argc != 2)
+ usage(1);
+ if (filename[0] == '-')
+ usage(1);
+
+ signal(SIGINT, on_interrupt);
+ signal(SIGTERM, on_interrupt);
+
+ App application = {0};
+ App *app = &application;
+
+ WdfHeader wdf = {0};
+ FILE *fp = fopen(filename, "rb");
+ if (fp != NULL)
+ fread(&wdf, sizeof(WdfHeader), 1, fp);
+ else
+ fprintf(stderr, "failed to read wdf file\n");
+ fclose(fp);
+
+ app->server = UA_Server_new();
+ UA_ServerConfig *config = UA_Server_getConfig(app->server);
+ UA_StatusCode status = UA_ServerConfig_setMinimal(config, port, NULL);
+ app->ns = UA_Server_addNamespace(app->server, "renishaw.spd");
+
+ // Add new object node for our data as Renishaw
+ UA_ObjectAttributes rAttr = UA_ObjectAttributes_default;
+ status = UA_Server_addObjectNode(app->server, UA_NODEID_STRING(app->ns, "renishaw"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
+ UA_QUALIFIEDNAME(app->ns, "Renishaw"),
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
+ rAttr, NULL, &app->renishawNode);
+
+ if (UA_StatusCode_isGood(status))
+ status = add_int32(app, "nspectra", "Capacity", wdf.nspectra);
+ if (UA_StatusCode_isGood(status))
+ status = add_int32(app, "ncollected", "Count", wdf.ncollected);
+ if (UA_StatusCode_isGood(status))
+ status = add_int32(app, "npoints", "Points", wdf.npoints);
+ if (UA_StatusCode_isGood(status))
+ status = add_float(app, "laserwavenum", "Laser Wavenumber", wdf.laserwavenum);
+
+ if (UA_StatusCode_isGood(status))
+ status = UA_Server_run(app->server, &is_running);
+
+ UA_Server_delete(app->server);
+ return UA_StatusCode_isGood(status) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
\ No newline at end of file