Skip to content

Commit

Permalink
server: expose Server.ServerConfiguration properties
Browse files Browse the repository at this point in the history
  • Loading branch information
erossignon committed Nov 20, 2023
1 parent 4d32977 commit 8a6eaf7
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 3 deletions.
19 changes: 17 additions & 2 deletions packages/node-opcua-server/source/opcua_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,9 @@ export class OPCUAServer extends OPCUABaseServer {
this.discoveryServerEndpointUrl = options.discoveryServerEndpointUrl || "opc.tcp://%FQDN%:4840";
assert(typeof this.discoveryServerEndpointUrl === "string");

this.serverInfo.applicationType = ApplicationType.Server;
this.serverInfo.applicationType =
options.serverInfo?.applicationType === undefined ? ApplicationType.Server : options.serverInfo.applicationType;

this.capabilitiesForMDNS = options.capabilitiesForMDNS || ["NA"];
this.registerServerMethod = options.registerServerMethod || RegisterServerMethod.HIDDEN;
_installRegisterServerManager(this);
Expand All @@ -1164,8 +1166,21 @@ export class OPCUAServer extends OPCUABaseServer {
applicationUri: () => this.serverInfo.applicationUri!,
buildInfo,
isAuditing: options.isAuditing,
serverCapabilities: options.serverCapabilities
serverCapabilities: options.serverCapabilities,

serverConfiguration: {
serverCapabilities: () => {
return this.capabilitiesForMDNS || ["NA"];
},
supportedPrivateKeyFormat: ["PEM"],
applicationType: () => this.serverInfo.applicationType,
applicationUri: () => this.serverInfo.applicationUri || "",
productUri: () => this.serverInfo.productUri || "",
// hasSecureElement: () => false,
multicastDnsEnabled: () => this.registerServerMethod === RegisterServerMethod.MDNS
}
});

this.objectFactory = new Factory(this.engine);

const endpointDefinitions: OPCUAServerEndpointOptions[] = options.alternateEndpoints || [];
Expand Down
80 changes: 79 additions & 1 deletion packages/node-opcua-server/source/server_engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ import {
CallMethodResultOptions,
ReadRequestOptions,
BrowseDescriptionOptions,
CallMethodRequest
CallMethodRequest,
ApplicationType
} from "node-opcua-types";
import { DataType, isValidVariant, Variant, VariantArrayType } from "node-opcua-variant";

Expand Down Expand Up @@ -287,7 +288,39 @@ function _get_next_subscriptionId() {
}

export type StringGetter = () => string;
export type StringArrayGetter = () => string[];
export type ApplicationTypeGetter = () => ApplicationType;
export type BooleanGetter = () => boolean;

export interface ServerConfigurationOptions {
applicationUri?: string | StringGetter;
applicationType?: ApplicationType | ApplicationTypeGetter; // default "Server"

hasSecureElement?: boolean | BooleanGetter; // default true

multicastDnsEnabled?: boolean | BooleanGetter; // default true

productUri?: string | StringGetter;

// /** @restricted only in professional version */
// resetToServerDefaults: () => Promise<void>;
// /** @restricted only in professional version */
// setAdminPassword?: (password: string) => Promise<void>;

/**
* The SupportedPrivateKeyFormats specifies the PrivateKey formats supported by the Server.
* Possible values include “PEM” (see RFC 5958) or “PFX” (see PKCS #12).
* @default ["PEM"]
*/
supportedPrivateKeyFormat: string[] | StringArrayGetter;

/**
* The ServerCapabilities Property specifies the capabilities from Annex D
* ( see https://reference.opcfoundation.org/GDS/v104/docs/D) which the Server supports. The value is
* the same as the value reported to the LocalDiscoveryServer when the Server calls the RegisterServer2 Service.
*/
serverCapabilities?: string[] | StringArrayGetter; // default|"N/A"]
}
export interface ServerEngineOptions {
applicationUri: string | StringGetter;

Expand All @@ -299,6 +332,7 @@ export interface ServerEngineOptions {
serverDiagnosticsEnabled?: boolean;
serverCapabilities?: ServerCapabilitiesOptions;
historyServerCapabilities?: HistoryServerCapabilitiesOptions;
serverConfiguration?: ServerConfigurationOptions;
}

export interface CreateSessionOption {
Expand All @@ -322,6 +356,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
public serverDiagnosticsEnabled: boolean;
public serverCapabilities: ServerCapabilities;
public historyServerCapabilities: HistoryServerCapabilities;
public serverConfiguration: ServerConfigurationOptions;
public clientDescription?: ApplicationDescription;

public addressSpace: AddressSpace | null;
Expand Down Expand Up @@ -367,6 +402,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
// --------------------------------------------------- ServerCapabilities
options.serverCapabilities = options.serverCapabilities || {};

options.serverConfiguration = options.serverConfiguration || {
supportedPrivateKeyFormat: ["PEM"]
};

// https://profiles.opcfoundation.org/profile
options.serverCapabilities.serverProfileArray = options.serverCapabilities.serverProfileArray || [
"http://opcfoundation.org/UA-Profile/Server/Standard", // Standard UA Server Profile",
Expand Down Expand Up @@ -405,6 +444,8 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
return MonitoredItem.minimumSamplingInterval;
});

this.serverConfiguration = options.serverConfiguration;

this.historyServerCapabilities = new HistoryServerCapabilities(options.historyServerCapabilities);

// --------------------------------------------------- serverDiagnosticsSummary extension Object
Expand Down Expand Up @@ -1133,12 +1174,49 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
});
};

type Getter<T> = () => T;
function r<T>(a: undefined | T | Getter<T>, defaultValue: T): T {
if (a === undefined) return defaultValue;
if (typeof a === "function") {
return (a as any)();
}
return a;
}
const bindServerConfigurationBasic = () => {
bindStandardArray(VariableIds.ServerConfiguration_ServerCapabilities, DataType.String, DataType.String, () =>
r(this.serverConfiguration.serverCapabilities, ["NA"])
);
bindStandardScalar(VariableIds.ServerConfiguration_ApplicationType, DataType.Int32, () =>
r(this.serverConfiguration.applicationType, ApplicationType.Server)
);
bindStandardScalar(VariableIds.ServerConfiguration_ApplicationUri, DataType.String, () =>
r(this.serverConfiguration.applicationUri, "")
);
bindStandardScalar(VariableIds.ServerConfiguration_ProductUri, DataType.String, () =>
r(this.serverConfiguration.productUri, "")
);
bindStandardScalar(VariableIds.ServerConfiguration_HasSecureElement, DataType.Boolean, () =>
r(this.serverConfiguration.hasSecureElement, false)
);
bindStandardScalar(VariableIds.ServerConfiguration_MulticastDnsEnabled, DataType.Boolean, () =>
r(this.serverConfiguration.multicastDnsEnabled, false)
);
bindStandardArray(
VariableIds.ServerConfiguration_SupportedPrivateKeyFormats,
DataType.String,
DataType.String,
() => r(this.serverConfiguration.supportedPrivateKeyFormat, ["PEM"])
);
};

bindServerDiagnostics();

bindServerStatus();

bindServerCapabilities();

bindServerConfigurationBasic();

bindHistoryServerCapabilities();

const bindExtraStuff = () => {
Expand Down
82 changes: 82 additions & 0 deletions packages/node-opcua-server/test/test_server_configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { nodesets } from "node-opcua-nodesets";
import { UAVariable } from "node-opcua-address-space-base";
import { OPCUAServer, RegisterServerMethod } from "..";
import should from "should";
import { ApplicationType } from "node-opcua-types";

const port = 2022;
// eslint-disable-next-line import/order
const describe = require("node-opcua-leak-detector").describeWithLeakDetector;

describe("OPCUAServer exposing serverConfiguration basic properties", () => {
let server: OPCUAServer;

const applicationType = ApplicationType.ClientAndServer;
before(async () => {
server = new OPCUAServer({
port,
nodeset_filename: [nodesets.standard],
capabilitiesForMDNS: ["DA", "HAD", "LDS"],
serverInfo: {
applicationType,
applicationName: { text: "SampleServer" },
productUri: "SampleServer"
},
registerServerMethod: RegisterServerMethod.MDNS

});
await server.start();
server.serverInfo.applicationType!.should.eql(ApplicationType.ClientAndServer);
});
after(async () => {
await server.shutdown();
});

function getServerConfiguration() {
const addressSpace = server.engine.addressSpace!;
const serverConfiguration = addressSpace.rootFolder.objects.server.getComponentByName("ServerConfiguration")!;
should.exist(serverConfiguration);
return serverConfiguration;
}
it("should have a serverConfiguration.serverCapabilities uaVariable with the correct information", () => {
const serverCapabilities = getServerConfiguration().getPropertyByName("ServerCapabilities") as UAVariable;
should.exist(serverCapabilities);

const serverCapabilitiesValue = serverCapabilities.readValue().value.value;

// console.log(serverCapabilitiesValue.toString());

serverCapabilitiesValue.should.eql(["DA", "HAD", "LDS"]);
});
it("should expose serverConfiguration.serverCapabilities.applicationType", () => {
const applicationType = getServerConfiguration().getPropertyByName("ApplicationType") as UAVariable;
should.exist(applicationType);

const applicationTypeValue = applicationType.readValue().value.value;
applicationTypeValue.should.eql(server.serverInfo.applicationType);
});
it("should expose serverConfiguration.serverCapabilities.productUri", () => {
const productUri = getServerConfiguration().getPropertyByName("ProductUri") as UAVariable;
should.exist(productUri);

const productUriValue = productUri.readValue().value.value;
productUriValue.should.eql("SampleServer");
});

it("should expose serverConfiguration.serverCapabilities.applicationUri", () => {
const applicationUri = getServerConfiguration().getPropertyByName("ApplicationUri") as UAVariable;
should.exist(applicationUri);

const applicationUriValue = applicationUri.readValue().value.value;
const expectedApplicationUri = server.serverInfo.applicationUri!;

applicationUriValue.should.eql(expectedApplicationUri);
});
it("should expose serverConfiguration.serverCapabilities.multicastDnsEnabled", () => {
const multicastDnsEnabled = getServerConfiguration().getPropertyByName("MulticastDnsEnabled") as UAVariable;
should.exist(multicastDnsEnabled);

const multicastDnsEnabledValue = multicastDnsEnabled.readValue().value.value;
multicastDnsEnabledValue.should.eql(true);
});
});

0 comments on commit 8a6eaf7

Please sign in to comment.